From 9e71e556dd9aad94a4bdf30834a5de638b9ee7fb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 10:52:05 +0330 Subject: [PATCH 001/775] New functions --- render/fe.go | 9 +++++++++ render/fewrite.go | 33 +++++++++++++++++++++++++++++++++ render/render.go | 25 +++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 render/fe.go create mode 100644 render/fewrite.go diff --git a/render/fe.go b/render/fe.go new file mode 100644 index 000000000..3b873b3d7 --- /dev/null +++ b/render/fe.go @@ -0,0 +1,9 @@ +package render + +import v3 "github.com/deadsy/sdfx/vec/v3" + +// Tetrahedron is a 3D tetrahedron. +// https://en.wikipedia.org/wiki/Tetrahedron +type Tetrahedron struct { + V [4]v3.Vec +} diff --git a/render/fewrite.go b/render/fewrite.go new file mode 100644 index 000000000..5caa31069 --- /dev/null +++ b/render/fewrite.go @@ -0,0 +1,33 @@ +package render + +import ( + "os" + "sync" +) + +// writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX file. +func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { + f, err := os.Create(path) + if err != nil { + return nil, err + } + + // External code writes triangles to this channel. + // This goroutine reads the channel and writes triangles to the file. + c := make(chan []*Tetrahedron) + + wg.Add(1) + go func() { + defer wg.Done() + defer f.Close() + + // read finite elements from the channel and write them to the file + for ts := range c { + for _, t := range ts { + _ = t + } + } + }() + + return c, nil +} diff --git a/render/render.go b/render/render.go index 4f254ed89..8782af096 100644 --- a/render/render.go +++ b/render/render.go @@ -52,6 +52,31 @@ func ToTriangles( //----------------------------------------------------------------------------- +// ToFE renders an SDF3 to finite elements in the shape of tetrahedra. +// Finite elements would then be written to an ABAQUS or CalculiX input file. +func ToFE( + s sdf.SDF3, // sdf3 to render + path string, // path to filename + r Render3, // rendering method +) { + fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) + // write the finite elements to an ABAQUS or CalculiX file + var wg sync.WaitGroup + output, err := writeFE(&wg, path) + if err != nil { + fmt.Printf("%s", err) + return + } + // run the renderer + r.Render(s, output) + // stop the FE writer reading on the channel + close(output) + // wait for the file write to complete + wg.Wait() +} + +//----------------------------------------------------------------------------- + // ToSTL renders an SDF3 to an STL file. func ToSTL( s sdf.SDF3, // sdf3 to render From 4096f91f5f9c965ffbf1f5feab514f7f0f8d7360 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 11:39:11 +0330 Subject: [PATCH 002/775] Comment --- render/fe.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/fe.go b/render/fe.go index 3b873b3d7..46e4a0d43 100644 --- a/render/fe.go +++ b/render/fe.go @@ -3,6 +3,7 @@ package render import v3 "github.com/deadsy/sdfx/vec/v3" // Tetrahedron is a 3D tetrahedron. +// It's a type of finite element, FE. // https://en.wikipedia.org/wiki/Tetrahedron type Tetrahedron struct { V [4]v3.Vec From e4a42f1503d62fce4b7e3e07853e55a777368089 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 11:42:08 +0330 Subject: [PATCH 003/775] Comment --- render/fewrite.go | 6 +++--- render/render.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/render/fewrite.go b/render/fewrite.go index 5caa31069..b0e369297 100644 --- a/render/fewrite.go +++ b/render/fewrite.go @@ -12,8 +12,8 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return nil, err } - // External code writes triangles to this channel. - // This goroutine reads the channel and writes triangles to the file. + // External code writes tetrahedra to this channel. + // This goroutine reads the channel and writes tetrahedra to the file. c := make(chan []*Tetrahedron) wg.Add(1) @@ -21,7 +21,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { defer wg.Done() defer f.Close() - // read finite elements from the channel and write them to the file + // read tetrahedra from the channel and write them to the file for ts := range c { for _, t := range ts { _ = t diff --git a/render/render.go b/render/render.go index 8782af096..c210b499f 100644 --- a/render/render.go +++ b/render/render.go @@ -53,14 +53,14 @@ func ToTriangles( //----------------------------------------------------------------------------- // ToFE renders an SDF3 to finite elements in the shape of tetrahedra. -// Finite elements would then be written to an ABAQUS or CalculiX input file. +// Tetrahedra would then be written to an ABAQUS or CalculiX input file. func ToFE( s sdf.SDF3, // sdf3 to render path string, // path to filename r Render3, // rendering method ) { fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) - // write the finite elements to an ABAQUS or CalculiX file + // write the tetrahedra to an ABAQUS or CalculiX file var wg sync.WaitGroup output, err := writeFE(&wg, path) if err != nil { From b94f4013c2f424e8bcd5326ecb35be0731bdfec7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 15:43:08 +0330 Subject: [PATCH 004/775] New render interface --- render/render.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/render/render.go b/render/render.go index c210b499f..608bfe8a7 100644 --- a/render/render.go +++ b/render/render.go @@ -29,6 +29,13 @@ type Render2 interface { Info(s sdf.SDF2) string } +// RenderFE renders a finite element mesh over the bounding volume of an sdf3. +// Finite elements are in the shape of tetrahedra. +type RenderFE interface { + Render(sdf3 sdf.SDF3, output chan<- []*Tetrahedron) + Info(sdf3 sdf.SDF3) string +} + //----------------------------------------------------------------------------- // ToTriangles renders an SDF3 to a triangle mesh. @@ -57,7 +64,7 @@ func ToTriangles( func ToFE( s sdf.SDF3, // sdf3 to render path string, // path to filename - r Render3, // rendering method + r RenderFE, // rendering method ) { fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) // write the tetrahedra to an ABAQUS or CalculiX file From b09c02ea334f0ed74b1aa05df7e491bddd88d545 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 15:57:41 +0330 Subject: [PATCH 005/775] New render type --- render/marchfe.go | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 render/marchfe.go diff --git a/render/marchfe.go b/render/marchfe.go new file mode 100644 index 000000000..dd12866c8 --- /dev/null +++ b/render/marchfe.go @@ -0,0 +1,56 @@ +package render + +import ( + "fmt" + + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" +) + +//----------------------------------------------------------------------------- + +func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tetrahedron { + // TODO: Logic. + return nil +} + +//----------------------------------------------------------------------------- + +// MarchingTetrahedraUniform renders using marching Tetrahedra with uniform space sampling. +type MarchingTetrahedraUniform struct { + meshCells int // number of cells on the longest axis of bounding box. e.g 200 +} + +// NewMarchingTetrahedraUniform returns a RenderFE object. +func NewMarchingTetrahedraUniform(meshCells int) *MarchingTetrahedraUniform { + return &MarchingTetrahedraUniform{ + meshCells: meshCells, + } +} + +// Info returns a string describing the rendered volume. +func (r *MarchingTetrahedraUniform) Info(s sdf.SDF3) string { + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + cells := conv.V3ToV3i(bb1Size) + return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) +} + +// Render produces a finite elements mesh over the bounding volume of an sdf3. +// Finite elements are in the shape of tetrahedra. +func (r *MarchingTetrahedraUniform) Render(s sdf.SDF3, output chan<- []*Tetrahedron) { + // work out the region we will sample + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + output <- marchingTetrahedra(s, bb, meshInc) +} + +//----------------------------------------------------------------------------- From 8fd0c535444ef546cd7a00e5cae408574ec4b9ed Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 15:59:40 +0330 Subject: [PATCH 006/775] Comment --- render/fe.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/fe.go b/render/fe.go index 46e4a0d43..8bc54d51f 100644 --- a/render/fe.go +++ b/render/fe.go @@ -3,7 +3,7 @@ package render import v3 "github.com/deadsy/sdfx/vec/v3" // Tetrahedron is a 3D tetrahedron. -// It's a type of finite element, FE. +// It's a kind of finite element, FE. // https://en.wikipedia.org/wiki/Tetrahedron type Tetrahedron struct { V [4]v3.Vec From f05b4d4800717176084cb4c512e9556a70f17191 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 16:00:44 +0330 Subject: [PATCH 007/775] TODO --- render/fewrite.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/fewrite.go b/render/fewrite.go index b0e369297..11ab9bfe5 100644 --- a/render/fewrite.go +++ b/render/fewrite.go @@ -25,6 +25,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { for ts := range c { for _, t := range ts { _ = t + // TODO. } } }() From b30a5b2a983838869666f8f2047df904efd5217c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 16:11:12 +0330 Subject: [PATCH 008/775] Example --- examples/finite_elements/main.go | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 examples/finite_elements/main.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go new file mode 100644 index 000000000..d45c22630 --- /dev/null +++ b/examples/finite_elements/main.go @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +/* + +Finite elements - tetrahedra - from triangle mesh. + +*/ +//----------------------------------------------------------------------------- + +package main + +import ( + "log" + "os" + + "github.com/deadsy/sdfx/obj" + "github.com/deadsy/sdfx/render" +) + +func main() { + stl := "../../files/teapot.stl" + + // read the stl file. + file, err := os.OpenFile(stl, os.O_RDONLY, 0400) + if err != nil { + log.Fatalf("error: %s", err) + } + + // create the SDF from the STL mesh + teapotSdf, err := obj.ImportSTL(file, 20, 3, 5) + if err != nil { + log.Fatalf("error: %s", err) + } + + // Render SDF3 to finite elements. + // Output file can be used by ABAQUS or CalculiX. + render.ToFE(teapotSdf, "teapot_fe.inp", render.NewMarchingTetrahedraUniform(200)) +} From 71500338187376a8e899b4a9ce4788d727737862 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 21 Feb 2023 17:08:37 +0330 Subject: [PATCH 009/775] Example log --- render/marchfe.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/marchfe.go b/render/marchfe.go index dd12866c8..4a69b2f93 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -11,6 +11,7 @@ import ( func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tetrahedron { // TODO: Logic. + fmt.Printf("marching tetrahedra, bbox center: %v , step: %v\n", s.BoundingBox().Center(), step) return nil } From e596259b62d6a055c03ab15fc7c1e91f9bb88483 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 22 Feb 2023 12:45:55 +0330 Subject: [PATCH 010/775] Hard-code tetrahedra to develop API --- render/marchfe.go | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/render/marchfe.go b/render/marchfe.go index 4a69b2f93..6a2db61ff 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -5,14 +5,39 @@ import ( "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" ) //----------------------------------------------------------------------------- func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tetrahedron { - // TODO: Logic. fmt.Printf("marching tetrahedra, bbox center: %v , step: %v\n", s.BoundingBox().Center(), step) - return nil + var tetrahedra []*Tetrahedron + + // Constant hard-coded tetrahedra vertices to develop and debug the output API. + // https://math.stackexchange.com/a/3311988/197913 + tetrahedra = append(tetrahedra, &Tetrahedron{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 0, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tetrahedron{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 0, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tetrahedron{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tetrahedron{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tetrahedron{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 0, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tetrahedron{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 0, Z: 1}}, + }) + + // TODO: Logic. + + return tetrahedra } //----------------------------------------------------------------------------- From ac20caaa98796f3f9588eb8d8d5dfddf6089f3c2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 22 Feb 2023 14:56:55 +0330 Subject: [PATCH 011/775] Write to output file: comments and heading --- render/fewrite.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/render/fewrite.go b/render/fewrite.go index 11ab9bfe5..322c0f30b 100644 --- a/render/fewrite.go +++ b/render/fewrite.go @@ -1,10 +1,32 @@ package render import ( + "bufio" + "encoding/binary" "os" "sync" + "time" ) +//----------------------------------------------------------------------------- + +// Define the ABAQUS or CalculiX inp file sections. + +type InpComments struct { + Text string // General comments. +} + +type InpHeading struct { + Title string // + Break0 string // + Model string // + Tab string // + Date string // + Break1 string // +} + +//----------------------------------------------------------------------------- + // writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX file. func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { f, err := os.Create(path) @@ -12,6 +34,34 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return nil, err } + // Use buffered IO for optimal IO writes. + // The default buffer size doesn't appear to limit performance. + buf := bufio.NewWriter(f) + + // write general comments + cmnts := InpComments{ + Text: `** + ** Structure: tetrahedral elements of a 3D model. + **\n`, + } + err = binary.Write(buf, binary.LittleEndian, &cmnts) + if err != nil { + return nil, err + } + + hdng := InpHeading{ + Title: "*HEADING", + Break0: "\n", + Model: "Model: 3D model", + Tab: "\t", + Date: "Date: " + time.Now().UTC().Format("2006-January-02 MST"), + Break1: "\n", + } + err = binary.Write(buf, binary.LittleEndian, &hdng) + if err != nil { + return nil, err + } + // External code writes tetrahedra to this channel. // This goroutine reads the channel and writes tetrahedra to the file. c := make(chan []*Tetrahedron) @@ -28,6 +78,9 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // TODO. } } + + // flush the tetrahedra + buf.Flush() }() return c, nil From de7a03509da9bb53be5c298cfc4eb29c7dd9f14b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 22 Feb 2023 15:31:03 +0330 Subject: [PATCH 012/775] Write fixed size data to file --- render/fewrite.go | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/render/fewrite.go b/render/fewrite.go index 322c0f30b..0a6e7c887 100644 --- a/render/fewrite.go +++ b/render/fewrite.go @@ -3,6 +3,7 @@ package render import ( "bufio" "encoding/binary" + "fmt" "os" "sync" "time" @@ -13,16 +14,16 @@ import ( // Define the ABAQUS or CalculiX inp file sections. type InpComments struct { - Text string // General comments. + Text [56]byte // General comments. } type InpHeading struct { - Title string // - Break0 string // - Model string // - Tab string // - Date string // - Break1 string // + Title [8]byte // + Break0 [1]byte // Line break. + Model [15]byte // + Tab [1]byte // Tab. + Date [26]byte // + Break1 [1]byte // Line break. } //----------------------------------------------------------------------------- @@ -39,24 +40,24 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { buf := bufio.NewWriter(f) // write general comments - cmnts := InpComments{ - Text: `** - ** Structure: tetrahedral elements of a 3D model. - **\n`, - } + cmnts := InpComments{} + copy(cmnts.Text[:], []byte("**\n** Structure: tetrahedral elements of a 3D model.\n**\n")) + + fmt.Println(len(cmnts.Text)) + err = binary.Write(buf, binary.LittleEndian, &cmnts) if err != nil { return nil, err } - hdng := InpHeading{ - Title: "*HEADING", - Break0: "\n", - Model: "Model: 3D model", - Tab: "\t", - Date: "Date: " + time.Now().UTC().Format("2006-January-02 MST"), - Break1: "\n", - } + hdng := InpHeading{} + copy(hdng.Title[:], []byte("*HEADING")) + copy(hdng.Break0[:], []byte("\n")) + copy(hdng.Model[:], []byte("Model: 3D model")) + copy(hdng.Tab[:], []byte("\t")) + copy(hdng.Date[:], []byte("Date: "+time.Now().UTC().Format("2006-January-02 MST"))) + copy(hdng.Break1[:], []byte("\n")) + err = binary.Write(buf, binary.LittleEndian, &hdng) if err != nil { return nil, err From 9c86045aaef02181c8638e4aa10ed9d32aebb5b0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 22 Feb 2023 15:32:36 +0330 Subject: [PATCH 013/775] Short month format --- render/fewrite.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/fewrite.go b/render/fewrite.go index 0a6e7c887..b7b3219a9 100644 --- a/render/fewrite.go +++ b/render/fewrite.go @@ -55,7 +55,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { copy(hdng.Break0[:], []byte("\n")) copy(hdng.Model[:], []byte("Model: 3D model")) copy(hdng.Tab[:], []byte("\t")) - copy(hdng.Date[:], []byte("Date: "+time.Now().UTC().Format("2006-January-02 MST"))) + copy(hdng.Date[:], []byte("Date: "+time.Now().UTC().Format("2006-Jan-02 MST"))) copy(hdng.Break1[:], []byte("\n")) err = binary.Write(buf, binary.LittleEndian, &hdng) From 3be041aace02ce1f7de3428ce1c714c78f048199 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 22 Feb 2023 15:34:54 +0330 Subject: [PATCH 014/775] Remove debug log --- render/fewrite.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/render/fewrite.go b/render/fewrite.go index b7b3219a9..8180c9475 100644 --- a/render/fewrite.go +++ b/render/fewrite.go @@ -3,7 +3,6 @@ package render import ( "bufio" "encoding/binary" - "fmt" "os" "sync" "time" @@ -43,8 +42,6 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { cmnts := InpComments{} copy(cmnts.Text[:], []byte("**\n** Structure: tetrahedral elements of a 3D model.\n**\n")) - fmt.Println(len(cmnts.Text)) - err = binary.Write(buf, binary.LittleEndian, &cmnts) if err != nil { return nil, err From 2c6ecb05a65db0ec144581cae1e18609a9cbcf50 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 10:59:41 +0330 Subject: [PATCH 015/775] Rename file --- render/{fewrite.go => inp.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename render/{fewrite.go => inp.go} (100%) diff --git a/render/fewrite.go b/render/inp.go similarity index 100% rename from render/fewrite.go rename to render/inp.go From 01a164f608eb88a9bfbcfabf64aebd17eafc8479 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 11:25:57 +0330 Subject: [PATCH 016/775] Clean up comments & heading --- render/inp.go | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/render/inp.go b/render/inp.go index 8180c9475..764896750 100644 --- a/render/inp.go +++ b/render/inp.go @@ -16,15 +16,32 @@ type InpComments struct { Text [56]byte // General comments. } +func NewInpComments() InpComments { + cmnts := InpComments{} + copy(cmnts.Text[:], []byte("**\n** Structure: tetrahedral elements of a 3D model.\n**\n")) + return cmnts +} + type InpHeading struct { Title [8]byte // Break0 [1]byte // Line break. Model [15]byte // Tab [1]byte // Tab. - Date [26]byte // + Date [21]byte // Exact size of text. Break1 [1]byte // Line break. } +func NewInpHeading() InpHeading { + hdng := InpHeading{} + copy(hdng.Title[:], []byte("*HEADING")) + copy(hdng.Break0[:], []byte("\n")) + copy(hdng.Model[:], []byte("Model: 3D model")) + copy(hdng.Tab[:], []byte("\t")) + copy(hdng.Date[:], []byte("Date: "+time.Now().UTC().Format("2006-Jan-02 MST"))) + copy(hdng.Break1[:], []byte("\n")) + return hdng +} + //----------------------------------------------------------------------------- // writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX file. @@ -38,23 +55,13 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // The default buffer size doesn't appear to limit performance. buf := bufio.NewWriter(f) - // write general comments - cmnts := InpComments{} - copy(cmnts.Text[:], []byte("**\n** Structure: tetrahedral elements of a 3D model.\n**\n")) - + cmnts := NewInpComments() err = binary.Write(buf, binary.LittleEndian, &cmnts) if err != nil { return nil, err } - hdng := InpHeading{} - copy(hdng.Title[:], []byte("*HEADING")) - copy(hdng.Break0[:], []byte("\n")) - copy(hdng.Model[:], []byte("Model: 3D model")) - copy(hdng.Tab[:], []byte("\t")) - copy(hdng.Date[:], []byte("Date: "+time.Now().UTC().Format("2006-Jan-02 MST"))) - copy(hdng.Break1[:], []byte("\n")) - + hdng := NewInpHeading() err = binary.Write(buf, binary.LittleEndian, &hdng) if err != nil { return nil, err From 653e006673362ec75dd64d42580b97ff9a838b90 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 11:45:14 +0330 Subject: [PATCH 017/775] INP comments section size --- render/inp.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/render/inp.go b/render/inp.go index 764896750..917d0fbcf 100644 --- a/render/inp.go +++ b/render/inp.go @@ -3,6 +3,7 @@ package render import ( "bufio" "encoding/binary" + "fmt" "os" "sync" "time" @@ -12,14 +13,20 @@ import ( // Define the ABAQUS or CalculiX inp file sections. +const sizeOfComments int = 104 + type InpComments struct { - Text [56]byte // General comments. + Text [sizeOfComments]byte // General comments. } -func NewInpComments() InpComments { +func NewInpComments() (*InpComments, error) { cmnts := InpComments{} - copy(cmnts.Text[:], []byte("**\n** Structure: tetrahedral elements of a 3D model.\n**\n")) - return cmnts + text := "**\n** Structure: tetrahedral elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" + if len(text) != sizeOfComments { + return nil, fmt.Errorf("INP file comments size mismatch: %v, %v", sizeOfComments, len(text)) + } + copy(cmnts.Text[:], []byte(text)) + return &cmnts, nil } type InpHeading struct { @@ -55,8 +62,11 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // The default buffer size doesn't appear to limit performance. buf := bufio.NewWriter(f) - cmnts := NewInpComments() - err = binary.Write(buf, binary.LittleEndian, &cmnts) + cmnts, err := NewInpComments() + if err != nil { + return nil, err + } + err = binary.Write(buf, binary.LittleEndian, *cmnts) if err != nil { return nil, err } From e67c164314cc1bacf0616b8e0b5106e3ac3b56ec Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 11:47:45 +0330 Subject: [PATCH 018/775] Simplify --- render/inp.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/render/inp.go b/render/inp.go index 917d0fbcf..ad654d3d4 100644 --- a/render/inp.go +++ b/render/inp.go @@ -3,7 +3,6 @@ package render import ( "bufio" "encoding/binary" - "fmt" "os" "sync" "time" @@ -13,20 +12,16 @@ import ( // Define the ABAQUS or CalculiX inp file sections. -const sizeOfComments int = 104 - type InpComments struct { - Text [sizeOfComments]byte // General comments. + Text [104]byte // General comments. } -func NewInpComments() (*InpComments, error) { +func NewInpComments() *InpComments { cmnts := InpComments{} + // Size of text is exactly 104: text := "**\n** Structure: tetrahedral elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" - if len(text) != sizeOfComments { - return nil, fmt.Errorf("INP file comments size mismatch: %v, %v", sizeOfComments, len(text)) - } copy(cmnts.Text[:], []byte(text)) - return &cmnts, nil + return &cmnts } type InpHeading struct { @@ -62,10 +57,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // The default buffer size doesn't appear to limit performance. buf := bufio.NewWriter(f) - cmnts, err := NewInpComments() - if err != nil { - return nil, err - } + cmnts := NewInpComments() err = binary.Write(buf, binary.LittleEndian, *cmnts) if err != nil { return nil, err From 14a1f07106e9496528c1fd979e21bcde51f66d4c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 11:49:57 +0330 Subject: [PATCH 019/775] Simplify --- render/inp.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/render/inp.go b/render/inp.go index ad654d3d4..3f8ea5d39 100644 --- a/render/inp.go +++ b/render/inp.go @@ -12,15 +12,16 @@ import ( // Define the ABAQUS or CalculiX inp file sections. +// Size of text is exactly 104: +const inpCommentsText = "**\n** Structure: tetrahedral elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" + type InpComments struct { Text [104]byte // General comments. } func NewInpComments() *InpComments { cmnts := InpComments{} - // Size of text is exactly 104: - text := "**\n** Structure: tetrahedral elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" - copy(cmnts.Text[:], []byte(text)) + copy(cmnts.Text[:], []byte(inpCommentsText)) return &cmnts } From 383bd14890d76abc90e75a0cfd497e1bd2713e15 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 11:51:27 +0330 Subject: [PATCH 020/775] Comment --- render/inp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/inp.go b/render/inp.go index 3f8ea5d39..feeec175d 100644 --- a/render/inp.go +++ b/render/inp.go @@ -26,9 +26,9 @@ func NewInpComments() *InpComments { } type InpHeading struct { - Title [8]byte // + Title [8]byte // Exact size of text. Break0 [1]byte // Line break. - Model [15]byte // + Model [15]byte // Exact size of text. Tab [1]byte // Tab. Date [21]byte // Exact size of text. Break1 [1]byte // Line break. From 7794fe8bfe93b89b7ed0fe22b739e8c46c3252e3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 11:54:05 +0330 Subject: [PATCH 021/775] Comment --- render/inp.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/inp.go b/render/inp.go index feeec175d..b5f594cf2 100644 --- a/render/inp.go +++ b/render/inp.go @@ -36,6 +36,7 @@ type InpHeading struct { func NewInpHeading() InpHeading { hdng := InpHeading{} + // Don't modify any of the following texts. Their sizes matter. copy(hdng.Title[:], []byte("*HEADING")) copy(hdng.Break0[:], []byte("\n")) copy(hdng.Model[:], []byte("Model: 3D model")) From f07dba243389d88e5e3d7285376d176e6f1b265b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 12:30:43 +0330 Subject: [PATCH 022/775] Simplify INP heading --- render/inp.go | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/render/inp.go b/render/inp.go index b5f594cf2..3f1998400 100644 --- a/render/inp.go +++ b/render/inp.go @@ -5,18 +5,17 @@ import ( "encoding/binary" "os" "sync" - "time" ) //----------------------------------------------------------------------------- // Define the ABAQUS or CalculiX inp file sections. -// Size of text is exactly 104: +// Don't modify the text. Size is exactly 104: const inpCommentsText = "**\n** Structure: tetrahedral elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" type InpComments struct { - Text [104]byte // General comments. + Text [104]byte // Exact size of text. } func NewInpComments() *InpComments { @@ -25,24 +24,16 @@ func NewInpComments() *InpComments { return &cmnts } +// Don't modify the text. Size is exactly 35: +const inpHeadingText = "*HEADING\nModel: 3D model Date: N/A\n" + type InpHeading struct { - Title [8]byte // Exact size of text. - Break0 [1]byte // Line break. - Model [15]byte // Exact size of text. - Tab [1]byte // Tab. - Date [21]byte // Exact size of text. - Break1 [1]byte // Line break. + Text [35]byte // Exact size of text. } func NewInpHeading() InpHeading { hdng := InpHeading{} - // Don't modify any of the following texts. Their sizes matter. - copy(hdng.Title[:], []byte("*HEADING")) - copy(hdng.Break0[:], []byte("\n")) - copy(hdng.Model[:], []byte("Model: 3D model")) - copy(hdng.Tab[:], []byte("\t")) - copy(hdng.Date[:], []byte("Date: "+time.Now().UTC().Format("2006-Jan-02 MST"))) - copy(hdng.Break1[:], []byte("\n")) + copy(hdng.Text[:], []byte(inpHeadingText)) return hdng } From ac6dfdb681526504d6a6beaa2392df8e40a9fc75 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 12:31:38 +0330 Subject: [PATCH 023/775] Rename --- render/inp.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/render/inp.go b/render/inp.go index 3f1998400..ba4539172 100644 --- a/render/inp.go +++ b/render/inp.go @@ -12,7 +12,7 @@ import ( // Define the ABAQUS or CalculiX inp file sections. // Don't modify the text. Size is exactly 104: -const inpCommentsText = "**\n** Structure: tetrahedral elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" +const inpComments = "**\n** Structure: tetrahedral elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" type InpComments struct { Text [104]byte // Exact size of text. @@ -20,12 +20,12 @@ type InpComments struct { func NewInpComments() *InpComments { cmnts := InpComments{} - copy(cmnts.Text[:], []byte(inpCommentsText)) + copy(cmnts.Text[:], []byte(inpComments)) return &cmnts } // Don't modify the text. Size is exactly 35: -const inpHeadingText = "*HEADING\nModel: 3D model Date: N/A\n" +const inpHeading = "*HEADING\nModel: 3D model Date: N/A\n" type InpHeading struct { Text [35]byte // Exact size of text. @@ -33,7 +33,7 @@ type InpHeading struct { func NewInpHeading() InpHeading { hdng := InpHeading{} - copy(hdng.Text[:], []byte(inpHeadingText)) + copy(hdng.Text[:], []byte(inpHeading)) return hdng } From 4afafd370e2e270e076f8fc77cfeadc50ac3f832 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 12:35:18 +0330 Subject: [PATCH 024/775] New comments text --- render/inp.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/render/inp.go b/render/inp.go index ba4539172..8ab8aa5c1 100644 --- a/render/inp.go +++ b/render/inp.go @@ -11,11 +11,11 @@ import ( // Define the ABAQUS or CalculiX inp file sections. -// Don't modify the text. Size is exactly 104: -const inpComments = "**\n** Structure: tetrahedral elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" +// Don't modify the text. Size is exactly 99: +const inpComments = "**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" type InpComments struct { - Text [104]byte // Exact size of text. + Text [99]byte // Exact size of text. } func NewInpComments() *InpComments { From f71910cb1c51f0bc187ca2fa4df22002ed0b4108 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 12:42:01 +0330 Subject: [PATCH 025/775] INP node section --- render/inp.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/render/inp.go b/render/inp.go index 8ab8aa5c1..bbc932c68 100644 --- a/render/inp.go +++ b/render/inp.go @@ -11,7 +11,7 @@ import ( // Define the ABAQUS or CalculiX inp file sections. -// Don't modify the text. Size is exactly 99: +// Don't modify the text. Its size matters. const inpComments = "**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" type InpComments struct { @@ -24,7 +24,7 @@ func NewInpComments() *InpComments { return &cmnts } -// Don't modify the text. Size is exactly 35: +// Don't modify the text. Its size matters. const inpHeading = "*HEADING\nModel: 3D model Date: N/A\n" type InpHeading struct { @@ -37,6 +37,19 @@ func NewInpHeading() InpHeading { return hdng } +// Don't modify the text. Its size matters. +const inpNode = "*NODE\n" + +type InpNode struct { + Text [6]byte // Exact size of text. +} + +func NewInpNode() InpNode { + nd := InpNode{} + copy(nd.Text[:], []byte(inpNode)) + return nd +} + //----------------------------------------------------------------------------- // writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX file. @@ -62,6 +75,11 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return nil, err } + err = binary.Write(buf, binary.LittleEndian, NewInpNode()) + if err != nil { + return nil, err + } + // External code writes tetrahedra to this channel. // This goroutine reads the channel and writes tetrahedra to the file. c := make(chan []*Tetrahedron) From 2b90e1c502ad640a4894ee124f0febb7a04222c0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 12:43:14 +0330 Subject: [PATCH 026/775] Simplify --- render/inp.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/render/inp.go b/render/inp.go index bbc932c68..bd726ab6d 100644 --- a/render/inp.go +++ b/render/inp.go @@ -18,10 +18,10 @@ type InpComments struct { Text [99]byte // Exact size of text. } -func NewInpComments() *InpComments { +func NewInpComments() InpComments { cmnts := InpComments{} copy(cmnts.Text[:], []byte(inpComments)) - return &cmnts + return cmnts } // Don't modify the text. Its size matters. @@ -63,14 +63,12 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // The default buffer size doesn't appear to limit performance. buf := bufio.NewWriter(f) - cmnts := NewInpComments() - err = binary.Write(buf, binary.LittleEndian, *cmnts) + err = binary.Write(buf, binary.LittleEndian, NewInpComments()) if err != nil { return nil, err } - hdng := NewInpHeading() - err = binary.Write(buf, binary.LittleEndian, &hdng) + err = binary.Write(buf, binary.LittleEndian, NewInpHeading()) if err != nil { return nil, err } From 0ca75c55a72cf2d641373837e0a4aef0b9dd24c5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 12:44:03 +0330 Subject: [PATCH 027/775] Rename --- render/inp.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/render/inp.go b/render/inp.go index bd726ab6d..9c0b8e8a7 100644 --- a/render/inp.go +++ b/render/inp.go @@ -12,15 +12,15 @@ import ( // Define the ABAQUS or CalculiX inp file sections. // Don't modify the text. Its size matters. -const inpComments = "**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" +const inpComment = "**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" -type InpComments struct { +type InpComment struct { Text [99]byte // Exact size of text. } -func NewInpComments() InpComments { - cmnts := InpComments{} - copy(cmnts.Text[:], []byte(inpComments)) +func NewInpComment() InpComment { + cmnts := InpComment{} + copy(cmnts.Text[:], []byte(inpComment)) return cmnts } @@ -63,7 +63,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // The default buffer size doesn't appear to limit performance. buf := bufio.NewWriter(f) - err = binary.Write(buf, binary.LittleEndian, NewInpComments()) + err = binary.Write(buf, binary.LittleEndian, NewInpComment()) if err != nil { return nil, err } From 8765a1de25aa6e8d3832b3befab699c6c50ffac0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 13:33:58 +0330 Subject: [PATCH 028/775] Use `encoding/gob` to write text to file --- render/inp.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/render/inp.go b/render/inp.go index 9c0b8e8a7..7b643cd24 100644 --- a/render/inp.go +++ b/render/inp.go @@ -2,7 +2,7 @@ package render import ( "bufio" - "encoding/binary" + "encoding/gob" "os" "sync" ) @@ -63,17 +63,20 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // The default buffer size doesn't appear to limit performance. buf := bufio.NewWriter(f) - err = binary.Write(buf, binary.LittleEndian, NewInpComment()) + // https://stackoverflow.com/a/65842289/3405291 + enc := gob.NewEncoder(buf) + + err = enc.Encode("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") if err != nil { return nil, err } - err = binary.Write(buf, binary.LittleEndian, NewInpHeading()) + err = enc.Encode("*HEADING\nModel: 3D model Date: N/A\n") if err != nil { return nil, err } - err = binary.Write(buf, binary.LittleEndian, NewInpNode()) + err = enc.Encode("*NODE\n") if err != nil { return nil, err } From 83c300c6feda19af36d759206245d77a32e8b2ae Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 14:11:05 +0330 Subject: [PATCH 029/775] Revert "Use `encoding/gob` to write text to file" This reverts commit 8765a1de25aa6e8d3832b3befab699c6c50ffac0. --- render/inp.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/render/inp.go b/render/inp.go index 7b643cd24..9c0b8e8a7 100644 --- a/render/inp.go +++ b/render/inp.go @@ -2,7 +2,7 @@ package render import ( "bufio" - "encoding/gob" + "encoding/binary" "os" "sync" ) @@ -63,20 +63,17 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // The default buffer size doesn't appear to limit performance. buf := bufio.NewWriter(f) - // https://stackoverflow.com/a/65842289/3405291 - enc := gob.NewEncoder(buf) - - err = enc.Encode("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") + err = binary.Write(buf, binary.LittleEndian, NewInpComment()) if err != nil { return nil, err } - err = enc.Encode("*HEADING\nModel: 3D model Date: N/A\n") + err = binary.Write(buf, binary.LittleEndian, NewInpHeading()) if err != nil { return nil, err } - err = enc.Encode("*NODE\n") + err = binary.Write(buf, binary.LittleEndian, NewInpNode()) if err != nil { return nil, err } From b12b263f89a2d9b35e60acc10542f5fa8ec6961a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 15:23:15 +0330 Subject: [PATCH 030/775] Simplify text writes --- render/inp.go | 44 ++++---------------------------------------- 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/render/inp.go b/render/inp.go index 9c0b8e8a7..ecc4084b3 100644 --- a/render/inp.go +++ b/render/inp.go @@ -2,7 +2,6 @@ package render import ( "bufio" - "encoding/binary" "os" "sync" ) @@ -11,43 +10,8 @@ import ( // Define the ABAQUS or CalculiX inp file sections. -// Don't modify the text. Its size matters. -const inpComment = "**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n" - -type InpComment struct { - Text [99]byte // Exact size of text. -} - -func NewInpComment() InpComment { - cmnts := InpComment{} - copy(cmnts.Text[:], []byte(inpComment)) - return cmnts -} - -// Don't modify the text. Its size matters. -const inpHeading = "*HEADING\nModel: 3D model Date: N/A\n" - -type InpHeading struct { - Text [35]byte // Exact size of text. -} - -func NewInpHeading() InpHeading { - hdng := InpHeading{} - copy(hdng.Text[:], []byte(inpHeading)) - return hdng -} - -// Don't modify the text. Its size matters. -const inpNode = "*NODE\n" - type InpNode struct { - Text [6]byte // Exact size of text. -} - -func NewInpNode() InpNode { - nd := InpNode{} - copy(nd.Text[:], []byte(inpNode)) - return nd + Id uint32 // } //----------------------------------------------------------------------------- @@ -63,17 +27,17 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // The default buffer size doesn't appear to limit performance. buf := bufio.NewWriter(f) - err = binary.Write(buf, binary.LittleEndian, NewInpComment()) + _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") if err != nil { return nil, err } - err = binary.Write(buf, binary.LittleEndian, NewInpHeading()) + _, err = f.WriteString("*HEADING\nModel: 3D model Date: N/A\n") if err != nil { return nil, err } - err = binary.Write(buf, binary.LittleEndian, NewInpNode()) + _, err = f.WriteString("*NODE\n") if err != nil { return nil, err } From 6ba8f498839c7e25239ed38562d098e3e36d267d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 15:41:17 +0330 Subject: [PATCH 031/775] Comma and space separator --- render/inp.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/render/inp.go b/render/inp.go index ecc4084b3..c96b98907 100644 --- a/render/inp.go +++ b/render/inp.go @@ -10,8 +10,21 @@ import ( // Define the ABAQUS or CalculiX inp file sections. +type Separator struct { + Comma byte + Space byte +} + +func NewSep() Separator { + return Separator{ + Comma: 0x2C, // Comma ASCII Character in hexadecimal. + Space: 0x20, // Space ASCII Character in hexadecimal. + } +} + type InpNode struct { - Id uint32 // + Id uint32 // + sep Separator // } //----------------------------------------------------------------------------- From 39b81977fd494ae42ba6b3b575b1aaeb9c723945 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 15:54:42 +0330 Subject: [PATCH 032/775] Write nodes as binary --- render/inp.go | 62 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/render/inp.go b/render/inp.go index c96b98907..2070a8f5b 100644 --- a/render/inp.go +++ b/render/inp.go @@ -2,31 +2,38 @@ package render import ( "bufio" + "encoding/binary" + "fmt" "os" "sync" ) //----------------------------------------------------------------------------- -// Define the ABAQUS or CalculiX inp file sections. +// Define the ABAQUS or CalculiX inp file requirements. -type Separator struct { - Comma byte - Space byte +type inpNode struct { + Id uint32 // + Comma0 byte // + X float32 // + Comma1 byte // + Y float32 // + Comma2 byte // + Z float32 // } -func NewSep() Separator { - return Separator{ - Comma: 0x2C, // Comma ASCII Character in hexadecimal. - Space: 0x20, // Space ASCII Character in hexadecimal. +func newInpNode(id uint32, x, y, z float32) inpNode { + return inpNode{ + Id: id, + Comma0: 0x2C, + X: x, + Comma1: 0x2C, + Y: y, + Comma2: 0x2C, + Z: z, } } -type InpNode struct { - Id uint32 // - sep Separator // -} - //----------------------------------------------------------------------------- // writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX file. @@ -64,11 +71,36 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { defer wg.Done() defer f.Close() + var nodeCount uint32 = 1 // Right, starts with 1 + var node inpNode // To avoid memory declaration inside the heavy loop. + // read tetrahedra from the channel and write them to the file for ts := range c { for _, t := range ts { - _ = t - // TODO. + node = newInpNode(nodeCount, float32(t.V[0].X), float32(t.V[0].Y), float32(t.V[0].Z)) + if err := binary.Write(buf, binary.LittleEndian, &node); err != nil { + fmt.Printf("%s\n", err) + return + } + nodeCount++ + node = newInpNode(nodeCount, float32(t.V[1].X), float32(t.V[1].Y), float32(t.V[1].Z)) + if err := binary.Write(buf, binary.LittleEndian, &node); err != nil { + fmt.Printf("%s\n", err) + return + } + nodeCount++ + node = newInpNode(nodeCount, float32(t.V[2].X), float32(t.V[2].Y), float32(t.V[2].Z)) + if err := binary.Write(buf, binary.LittleEndian, &node); err != nil { + fmt.Printf("%s\n", err) + return + } + nodeCount++ + node = newInpNode(nodeCount, float32(t.V[2].X), float32(t.V[2].Y), float32(t.V[2].Z)) + if err := binary.Write(buf, binary.LittleEndian, &node); err != nil { + fmt.Printf("%s\n", err) + return + } + nodeCount++ } } From f6412bf0ba77962ef9d524699a21a06c3910d70b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 16:02:38 +0330 Subject: [PATCH 033/775] Write nodes as text --- render/inp.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/render/inp.go b/render/inp.go index 2070a8f5b..525a13fdc 100644 --- a/render/inp.go +++ b/render/inp.go @@ -2,7 +2,6 @@ package render import ( "bufio" - "encoding/binary" "fmt" "os" "sync" @@ -72,31 +71,30 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { defer f.Close() var nodeCount uint32 = 1 // Right, starts with 1 - var node inpNode // To avoid memory declaration inside the heavy loop. // read tetrahedra from the channel and write them to the file for ts := range c { for _, t := range ts { - node = newInpNode(nodeCount, float32(t.V[0].X), float32(t.V[0].Y), float32(t.V[0].Z)) - if err := binary.Write(buf, binary.LittleEndian, &node); err != nil { + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[0].X), float32(t.V[0].Y), float32(t.V[0].Z))) + if err != nil { fmt.Printf("%s\n", err) return } nodeCount++ - node = newInpNode(nodeCount, float32(t.V[1].X), float32(t.V[1].Y), float32(t.V[1].Z)) - if err := binary.Write(buf, binary.LittleEndian, &node); err != nil { + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[1].X), float32(t.V[1].Y), float32(t.V[1].Z))) + if err != nil { fmt.Printf("%s\n", err) return } nodeCount++ - node = newInpNode(nodeCount, float32(t.V[2].X), float32(t.V[2].Y), float32(t.V[2].Z)) - if err := binary.Write(buf, binary.LittleEndian, &node); err != nil { + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[2].X), float32(t.V[2].Y), float32(t.V[2].Z))) + if err != nil { fmt.Printf("%s\n", err) return } nodeCount++ - node = newInpNode(nodeCount, float32(t.V[2].X), float32(t.V[2].Y), float32(t.V[2].Z)) - if err := binary.Write(buf, binary.LittleEndian, &node); err != nil { + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[2].X), float32(t.V[2].Y), float32(t.V[2].Z))) + if err != nil { fmt.Printf("%s\n", err) return } From 98189693c4a170b382aeebdcb3a69caf73d8f99b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 23 Feb 2023 16:03:31 +0330 Subject: [PATCH 034/775] Clean up extra types and comment --- render/inp.go | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/render/inp.go b/render/inp.go index 525a13fdc..63ad7c187 100644 --- a/render/inp.go +++ b/render/inp.go @@ -9,33 +9,11 @@ import ( //----------------------------------------------------------------------------- -// Define the ABAQUS or CalculiX inp file requirements. - -type inpNode struct { - Id uint32 // - Comma0 byte // - X float32 // - Comma1 byte // - Y float32 // - Comma2 byte // - Z float32 // -} - -func newInpNode(id uint32, x, y, z float32) inpNode { - return inpNode{ - Id: id, - Comma0: 0x2C, - X: x, - Comma1: 0x2C, - Y: y, - Comma2: 0x2C, - Z: z, - } -} +// Define the ABAQUS or CalculiX inp file requirements, if any. //----------------------------------------------------------------------------- -// writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX file. +// writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { f, err := os.Create(path) if err != nil { From 94c9a2c09af85c20c68654d07db184496f24b8fc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 10:43:01 +0330 Subject: [PATCH 035/775] Date on heading --- render/inp.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/render/inp.go b/render/inp.go index 63ad7c187..3bc0c94b0 100644 --- a/render/inp.go +++ b/render/inp.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "sync" + "time" ) //----------------------------------------------------------------------------- @@ -29,7 +30,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return nil, err } - _, err = f.WriteString("*HEADING\nModel: 3D model Date: N/A\n") + _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") if err != nil { return nil, err } From 9c1cabda340853e3ebd0735dc4ca664ae4cb1280 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 10:49:28 +0330 Subject: [PATCH 036/775] Relocate node section title writing --- render/inp.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/render/inp.go b/render/inp.go index 3bc0c94b0..98451a212 100644 --- a/render/inp.go +++ b/render/inp.go @@ -35,11 +35,6 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return nil, err } - _, err = f.WriteString("*NODE\n") - if err != nil { - return nil, err - } - // External code writes tetrahedra to this channel. // This goroutine reads the channel and writes tetrahedra to the file. c := make(chan []*Tetrahedron) @@ -49,6 +44,12 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { defer wg.Done() defer f.Close() + _, err = f.WriteString("*NODE\n") + if err != nil { + fmt.Printf("%s\n", err) + return + } + var nodeCount uint32 = 1 // Right, starts with 1 // read tetrahedra from the channel and write them to the file From 32b30d675aba4eebc3c4e9fe0af9451934308069 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 11:17:36 +0330 Subject: [PATCH 037/775] Write elements --- render/inp.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/render/inp.go b/render/inp.go index 98451a212..bf5e7dfdf 100644 --- a/render/inp.go +++ b/render/inp.go @@ -51,6 +51,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { } var nodeCount uint32 = 1 // Right, starts with 1 + var tetCount uint32 = 0 // // read tetrahedra from the channel and write them to the file for ts := range c { @@ -79,9 +80,30 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return } nodeCount++ + tetCount++ } } + _, err = f.WriteString("*ELEMENT, TYPE=C3D4\n") + if err != nil { + fmt.Printf("%s\n", err) + return + } + + inc := func(i *uint32) uint32 { *i++; return *i } + + var eleId uint32 = 1 // Right, start with 1 + var nodeIdx uint32 = 0 + + for i := 0; i < int(tetCount); i++ { + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleId, inc(&nodeIdx), inc(&nodeIdx), inc(&nodeIdx), inc(&nodeIdx))) + if err != nil { + fmt.Printf("%s\n", err) + return + } + eleId++ + } + // flush the tetrahedra buf.Flush() }() From fb98255140d6aa8c1ddfa145c6151346bc16da32 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 11:19:59 +0330 Subject: [PATCH 038/775] New increment func --- render/inp.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/render/inp.go b/render/inp.go index bf5e7dfdf..ca23c65d1 100644 --- a/render/inp.go +++ b/render/inp.go @@ -90,8 +90,6 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return } - inc := func(i *uint32) uint32 { *i++; return *i } - var eleId uint32 = 1 // Right, start with 1 var nodeIdx uint32 = 0 @@ -110,3 +108,9 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return c, nil } + +// https://stackoverflow.com/a/56015749/3405291 +func inc(i *uint32) uint32 { + *i++ + return *i +} From 13ca48be1143ac54eed232a101d58a6192b7a994 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 11:22:35 +0330 Subject: [PATCH 039/775] Comment --- render/inp.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/inp.go b/render/inp.go index ca23c65d1..cc19d2fa9 100644 --- a/render/inp.go +++ b/render/inp.go @@ -109,6 +109,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return c, nil } +// To be able to increment values in-place. // https://stackoverflow.com/a/56015749/3405291 func inc(i *uint32) uint32 { *i++ From 8b9e0857d513e90939cd9a3de395ca9e1f716235 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 11:23:48 +0330 Subject: [PATCH 040/775] Comment --- render/inp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/inp.go b/render/inp.go index cc19d2fa9..6c5cb6038 100644 --- a/render/inp.go +++ b/render/inp.go @@ -90,8 +90,8 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return } - var eleId uint32 = 1 // Right, start with 1 - var nodeIdx uint32 = 0 + var eleId uint32 = 1 // Right, start with 1 + var nodeIdx uint32 = 0 // Will be incremented. So will be starting from 1. for i := 0; i < int(tetCount); i++ { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleId, inc(&nodeIdx), inc(&nodeIdx), inc(&nodeIdx), inc(&nodeIdx))) From 0c591a6bd35ce558b84bab3b507a2873952b7bec Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 11:29:14 +0330 Subject: [PATCH 041/775] Element set name --- render/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/inp.go b/render/inp.go index 6c5cb6038..f3b99fd9a 100644 --- a/render/inp.go +++ b/render/inp.go @@ -84,7 +84,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { } } - _, err = f.WriteString("*ELEMENT, TYPE=C3D4\n") + _, err = f.WriteString("*ELEMENT, TYPE=C3D4, ELSET=Eall\n") if err != nil { fmt.Printf("%s\n", err) return From 4202f2a6a092290961fa03cc97b3c160aa2adfd5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 11:43:38 +0330 Subject: [PATCH 042/775] Remove: buffered IO is not used any longer --- render/inp.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/render/inp.go b/render/inp.go index f3b99fd9a..23d29d0a5 100644 --- a/render/inp.go +++ b/render/inp.go @@ -1,7 +1,6 @@ package render import ( - "bufio" "fmt" "os" "sync" @@ -21,10 +20,6 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return nil, err } - // Use buffered IO for optimal IO writes. - // The default buffer size doesn't appear to limit performance. - buf := bufio.NewWriter(f) - _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") if err != nil { return nil, err @@ -101,9 +96,6 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { } eleId++ } - - // flush the tetrahedra - buf.Flush() }() return c, nil From a37bf7954ff4d20917645d2453dfcd9f089f3c2b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 11:54:18 +0330 Subject: [PATCH 043/775] Rename --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index d45c22630..2b0e9b049 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -33,5 +33,5 @@ func main() { // Render SDF3 to finite elements. // Output file can be used by ABAQUS or CalculiX. - render.ToFE(teapotSdf, "teapot_fe.inp", render.NewMarchingTetrahedraUniform(200)) + render.ToFE(teapotSdf, "teapot.inp", render.NewMarchingTetrahedraUniform(200)) } From ec5a14263d23851fcd72350a8bf6a975df48d035 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 12:03:06 +0330 Subject: [PATCH 044/775] Fix simple tetrahedra coordinates --- render/marchfe.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/render/marchfe.go b/render/marchfe.go index 6a2db61ff..92eeab708 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -15,24 +15,24 @@ func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tetrahedron { var tetrahedra []*Tetrahedron // Constant hard-coded tetrahedra vertices to develop and debug the output API. - // https://math.stackexchange.com/a/3311988/197913 + // https://cs.stackexchange.com/a/90011/67985 tetrahedra = append(tetrahedra, &Tetrahedron{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 0, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, }) tetrahedra = append(tetrahedra, &Tetrahedron{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 0, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, }) tetrahedra = append(tetrahedra, &Tetrahedron{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, }) tetrahedra = append(tetrahedra, &Tetrahedron{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, }) tetrahedra = append(tetrahedra, &Tetrahedron{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 0, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, }) tetrahedra = append(tetrahedra, &Tetrahedron{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 0, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, }) // TODO: Logic. From c7c4d88beac297e490cda87fab5e47a237909bf2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 12:59:07 +0330 Subject: [PATCH 045/775] Fix a bug --- render/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/inp.go b/render/inp.go index 23d29d0a5..371fc3da5 100644 --- a/render/inp.go +++ b/render/inp.go @@ -69,7 +69,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { return } nodeCount++ - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[2].X), float32(t.V[2].Y), float32(t.V[2].Z))) + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[3].X), float32(t.V[3].Y), float32(t.V[3].Z))) if err != nil { fmt.Printf("%s\n", err) return From a2fd9bed5ebb33c747c9503efbe4409e6fc424a5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:18:12 +0330 Subject: [PATCH 046/775] New mesh --- render/fe.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/render/fe.go b/render/fe.go index 8bc54d51f..0afeecff5 100644 --- a/render/fe.go +++ b/render/fe.go @@ -8,3 +8,7 @@ import v3 "github.com/deadsy/sdfx/vec/v3" type Tetrahedron struct { V [4]v3.Vec } + +// A mesh of tetrahedra with 4 nodes. +type MeshTet4 struct { +} From e7c848bd995d9fdacd8f8c674e67e1346d5238e6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:19:01 +0330 Subject: [PATCH 047/775] Rename to Tet4 --- render/fe.go | 6 +++--- render/inp.go | 4 ++-- render/marchfe.go | 18 +++++++++--------- render/render.go | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/render/fe.go b/render/fe.go index 0afeecff5..ce94edc9c 100644 --- a/render/fe.go +++ b/render/fe.go @@ -2,10 +2,10 @@ package render import v3 "github.com/deadsy/sdfx/vec/v3" -// Tetrahedron is a 3D tetrahedron. +// Tet4 is a 3D tetrahedron consisting of 4 nodes. // It's a kind of finite element, FE. -// https://en.wikipedia.org/wiki/Tetrahedron -type Tetrahedron struct { +// https://en.wikipedia.org/wiki/Tet4 +type Tet4 struct { V [4]v3.Vec } diff --git a/render/inp.go b/render/inp.go index 371fc3da5..6dbbb30ef 100644 --- a/render/inp.go +++ b/render/inp.go @@ -14,7 +14,7 @@ import ( //----------------------------------------------------------------------------- // writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. -func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { +func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tet4, error) { f, err := os.Create(path) if err != nil { return nil, err @@ -32,7 +32,7 @@ func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tetrahedron, error) { // External code writes tetrahedra to this channel. // This goroutine reads the channel and writes tetrahedra to the file. - c := make(chan []*Tetrahedron) + c := make(chan []*Tet4) wg.Add(1) go func() { diff --git a/render/marchfe.go b/render/marchfe.go index 92eeab708..c19f2bb1f 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -10,28 +10,28 @@ import ( //----------------------------------------------------------------------------- -func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tetrahedron { +func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { fmt.Printf("marching tetrahedra, bbox center: %v , step: %v\n", s.BoundingBox().Center(), step) - var tetrahedra []*Tetrahedron + var tetrahedra []*Tet4 // Constant hard-coded tetrahedra vertices to develop and debug the output API. // https://cs.stackexchange.com/a/90011/67985 - tetrahedra = append(tetrahedra, &Tetrahedron{ + tetrahedra = append(tetrahedra, &Tet4{ V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, }) - tetrahedra = append(tetrahedra, &Tetrahedron{ + tetrahedra = append(tetrahedra, &Tet4{ V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, }) - tetrahedra = append(tetrahedra, &Tetrahedron{ + tetrahedra = append(tetrahedra, &Tet4{ V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, }) - tetrahedra = append(tetrahedra, &Tetrahedron{ + tetrahedra = append(tetrahedra, &Tet4{ V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, }) - tetrahedra = append(tetrahedra, &Tetrahedron{ + tetrahedra = append(tetrahedra, &Tet4{ V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, }) - tetrahedra = append(tetrahedra, &Tetrahedron{ + tetrahedra = append(tetrahedra, &Tet4{ V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, }) @@ -67,7 +67,7 @@ func (r *MarchingTetrahedraUniform) Info(s sdf.SDF3) string { // Render produces a finite elements mesh over the bounding volume of an sdf3. // Finite elements are in the shape of tetrahedra. -func (r *MarchingTetrahedraUniform) Render(s sdf.SDF3, output chan<- []*Tetrahedron) { +func (r *MarchingTetrahedraUniform) Render(s sdf.SDF3, output chan<- []*Tet4) { // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() diff --git a/render/render.go b/render/render.go index 608bfe8a7..ebed1a7b0 100644 --- a/render/render.go +++ b/render/render.go @@ -32,7 +32,7 @@ type Render2 interface { // RenderFE renders a finite element mesh over the bounding volume of an sdf3. // Finite elements are in the shape of tetrahedra. type RenderFE interface { - Render(sdf3 sdf.SDF3, output chan<- []*Tetrahedron) + Render(sdf3 sdf.SDF3, output chan<- []*Tet4) Info(sdf3 sdf.SDF3) string } From 1bd8b5278a4a898ec9f8914dc4b4a80ef85c62c1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:30:30 +0330 Subject: [PATCH 048/775] Mesh data structure --- render/fe.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/render/fe.go b/render/fe.go index ce94edc9c..c328108fb 100644 --- a/render/fe.go +++ b/render/fe.go @@ -10,5 +10,11 @@ type Tet4 struct { } // A mesh of tetrahedra with 4 nodes. +// A sophisticated data structure for mesh is required to store tetrahedra. +// The repeated nodes would be removed. +// The element connectivity would be created with unique nodes. type MeshTet4 struct { + T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. + V []v3.Vec // Vertex buffer. All unique. + Lookup map[[4]float32]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. } From 8f19dfd9ed732c3273e59cfea49be199338c0c33 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:49:44 +0330 Subject: [PATCH 049/775] Tet4 mesh funcs --- render/fe.go | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/render/fe.go b/render/fe.go index c328108fb..70d0e5ed4 100644 --- a/render/fe.go +++ b/render/fe.go @@ -16,5 +16,48 @@ type Tet4 struct { type MeshTet4 struct { T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. V []v3.Vec // Vertex buffer. All unique. - Lookup map[[4]float32]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. + Lookup map[[3]float32]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. + vCount uint32 // TODO: Remove? +} + +func NewMeshTet4() *MeshTet4 { + return &MeshTet4{ + T: []uint32{}, + V: []v3.Vec{}, + Lookup: map[[3]float32]uint32{}, + } +} + +// Just an optimization, if there is an estimation of tetrahedra count. +// Affects the speed according to experiments. +func (m *MeshTet4) Allocate(tetCount uint32) { + m.T = make([]uint32, tetCount*4) + m.V = make([]v3.Vec, tetCount/4*2) // By experimenting. + m.Lookup = make(map[[3]float32]uint32, tetCount/4*2) +} + +func (t *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { + // The node numbering should follow the convention of CalculiX. + // http://www.dhondt.de/ccx_2.20.pdf + t.T[i*4], t.T[i*4+1], t.T[i*4+2], t.T[i*4+3] = t.AddVertex(a), t.AddVertex(b), t.AddVertex(c), t.AddVertex(d) +} + +func (t *MeshTet4) AddVertex(vert v3.Vec) uint32 { + // TODO: Binary insertion sort and search to eliminate extra allocation + // TODO: Consider epsilon in comparison and use int (*100) for searching + if vertID, ok := t.Lookup[[3]float32{float32(vert.X), float32(vert.Y), float32(vert.Z)}]; ok { + return vertID + } + if t.VertexCount() <= int(t.vCount) { + t.V = append(t.V, vert) + } else { + t.V[t.vCount] = vert + } + t.Lookup[[3]float32{float32(vert.X), float32(vert.Y), float32(vert.Z)}] = t.vCount + t.vCount++ + return t.vCount - 1 +} + +func (m *MeshTet4) VertexCount() int { + return len(m.V) } From d6002c727e89ab75ddbabcd38910474a464bec9f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:52:03 +0330 Subject: [PATCH 050/775] Rename file --- render/{fe.go => tet4.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename render/{fe.go => tet4.go} (100%) diff --git a/render/fe.go b/render/tet4.go similarity index 100% rename from render/fe.go rename to render/tet4.go From a45eac6e225fa8ee44276415acd49007dd1e2be1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:53:36 +0330 Subject: [PATCH 051/775] Rename file --- render/{marchfe.go => marchtet4.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename render/{marchfe.go => marchtet4.go} (100%) diff --git a/render/marchfe.go b/render/marchtet4.go similarity index 100% rename from render/marchfe.go rename to render/marchtet4.go From af61b40976b36cd6fb005fb5e9a62b23e71774a5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:57:35 +0330 Subject: [PATCH 052/775] Remove allocation optimization --- render/tet4.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 70d0e5ed4..ab241102a 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -28,15 +28,10 @@ func NewMeshTet4() *MeshTet4 { } } -// Just an optimization, if there is an estimation of tetrahedra count. -// Affects the speed according to experiments. -func (m *MeshTet4) Allocate(tetCount uint32) { - m.T = make([]uint32, tetCount*4) - m.V = make([]v3.Vec, tetCount/4*2) // By experimenting. - m.Lookup = make(map[[3]float32]uint32, tetCount/4*2) -} - func (t *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { + // Make room for 4 new indices. + t.T = append(t.T, 0, 0, 0, 0) + // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf t.T[i*4], t.T[i*4+1], t.T[i*4+2], t.T[i*4+3] = t.AddVertex(a), t.AddVertex(b), t.AddVertex(c), t.AddVertex(d) From bdd9f9c3b1457b668a7f1eb29621ddea21ea44c5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:58:29 +0330 Subject: [PATCH 053/775] Revert "Remove allocation optimization" This reverts commit af61b40976b36cd6fb005fb5e9a62b23e71774a5. --- render/tet4.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index ab241102a..70d0e5ed4 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -28,10 +28,15 @@ func NewMeshTet4() *MeshTet4 { } } -func (t *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { - // Make room for 4 new indices. - t.T = append(t.T, 0, 0, 0, 0) +// Just an optimization, if there is an estimation of tetrahedra count. +// Affects the speed according to experiments. +func (m *MeshTet4) Allocate(tetCount uint32) { + m.T = make([]uint32, tetCount*4) + m.V = make([]v3.Vec, tetCount/4*2) // By experimenting. + m.Lookup = make(map[[3]float32]uint32, tetCount/4*2) +} +func (t *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf t.T[i*4], t.T[i*4+1], t.T[i*4+2], t.T[i*4+3] = t.AddVertex(a), t.AddVertex(b), t.AddVertex(c), t.AddVertex(d) From dea1e07990f2807814e428e3397e9b539a9b4b5d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 13:59:42 +0330 Subject: [PATCH 054/775] Rename --- render/tet4.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 70d0e5ed4..632304234 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -36,26 +36,26 @@ func (m *MeshTet4) Allocate(tetCount uint32) { m.Lookup = make(map[[3]float32]uint32, tetCount/4*2) } -func (t *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { +func (m *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf - t.T[i*4], t.T[i*4+1], t.T[i*4+2], t.T[i*4+3] = t.AddVertex(a), t.AddVertex(b), t.AddVertex(c), t.AddVertex(d) + m.T[i*4], m.T[i*4+1], m.T[i*4+2], m.T[i*4+3] = m.AddVertex(a), m.AddVertex(b), m.AddVertex(c), m.AddVertex(d) } -func (t *MeshTet4) AddVertex(vert v3.Vec) uint32 { +func (m *MeshTet4) AddVertex(vert v3.Vec) uint32 { // TODO: Binary insertion sort and search to eliminate extra allocation // TODO: Consider epsilon in comparison and use int (*100) for searching - if vertID, ok := t.Lookup[[3]float32{float32(vert.X), float32(vert.Y), float32(vert.Z)}]; ok { + if vertID, ok := m.Lookup[[3]float32{float32(vert.X), float32(vert.Y), float32(vert.Z)}]; ok { return vertID } - if t.VertexCount() <= int(t.vCount) { - t.V = append(t.V, vert) + if m.VertexCount() <= int(m.vCount) { + m.V = append(m.V, vert) } else { - t.V[t.vCount] = vert + m.V[m.vCount] = vert } - t.Lookup[[3]float32{float32(vert.X), float32(vert.Y), float32(vert.Z)}] = t.vCount - t.vCount++ - return t.vCount - 1 + m.Lookup[[3]float32{float32(vert.X), float32(vert.Y), float32(vert.Z)}] = m.vCount + m.vCount++ + return m.vCount - 1 } func (m *MeshTet4) VertexCount() int { From a27624b92f66edf36e1244da8022fb017c1bed00 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 14:01:51 +0330 Subject: [PATCH 055/775] Comment --- render/tet4.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 632304234..fd3a89447 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -28,11 +28,13 @@ func NewMeshTet4() *MeshTet4 { } } -// Just an optimization, if there is an estimation of tetrahedra count. -// Affects the speed according to experiments. func (m *MeshTet4) Allocate(tetCount uint32) { m.T = make([]uint32, tetCount*4) - m.V = make([]v3.Vec, tetCount/4*2) // By experimenting. + + // Just an optimization by experimenting. + // Affects the speed according to experiments. + m.V = make([]v3.Vec, tetCount/4*2) + m.Lookup = make(map[[3]float32]uint32, tetCount/4*2) } From bf886bf294689a01f0e8cc51328b528406fceccd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 14:14:34 +0330 Subject: [PATCH 056/775] Use float64 --- render/tet4.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index fd3a89447..11d32000a 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -16,7 +16,7 @@ type Tet4 struct { type MeshTet4 struct { T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. V []v3.Vec // Vertex buffer. All unique. - Lookup map[[3]float32]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. + Lookup map[[3]float64]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. vCount uint32 // TODO: Remove? } @@ -24,7 +24,7 @@ func NewMeshTet4() *MeshTet4 { return &MeshTet4{ T: []uint32{}, V: []v3.Vec{}, - Lookup: map[[3]float32]uint32{}, + Lookup: map[[3]float64]uint32{}, } } @@ -35,7 +35,7 @@ func (m *MeshTet4) Allocate(tetCount uint32) { // Affects the speed according to experiments. m.V = make([]v3.Vec, tetCount/4*2) - m.Lookup = make(map[[3]float32]uint32, tetCount/4*2) + m.Lookup = make(map[[3]float64]uint32, tetCount/4*2) } func (m *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { @@ -47,7 +47,7 @@ func (m *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { func (m *MeshTet4) AddVertex(vert v3.Vec) uint32 { // TODO: Binary insertion sort and search to eliminate extra allocation // TODO: Consider epsilon in comparison and use int (*100) for searching - if vertID, ok := m.Lookup[[3]float32{float32(vert.X), float32(vert.Y), float32(vert.Z)}]; ok { + if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { return vertID } if m.VertexCount() <= int(m.vCount) { @@ -55,7 +55,7 @@ func (m *MeshTet4) AddVertex(vert v3.Vec) uint32 { } else { m.V[m.vCount] = vert } - m.Lookup[[3]float32{float32(vert.X), float32(vert.Y), float32(vert.Z)}] = m.vCount + m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = m.vCount m.vCount++ return m.vCount - 1 } From c3022f66edc2ff2a0f55c09231708c31ec4bcbeb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 14:24:33 +0330 Subject: [PATCH 057/775] Finalize func --- render/tet4.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 11d32000a..6f57e4ecc 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -1,10 +1,14 @@ package render -import v3 "github.com/deadsy/sdfx/vec/v3" +import ( + "runtime" + + v3 "github.com/deadsy/sdfx/vec/v3" +) // Tet4 is a 3D tetrahedron consisting of 4 nodes. // It's a kind of finite element, FE. -// https://en.wikipedia.org/wiki/Tet4 +// https://en.wikipedia.org/wiki/Tetrahedron type Tet4 struct { V [4]v3.Vec } @@ -63,3 +67,10 @@ func (m *MeshTet4) AddVertex(vert v3.Vec) uint32 { func (m *MeshTet4) VertexCount() int { return len(m.V) } + +func (t *MeshTet4) Finalize() { + t.V = t.V[:t.vCount] + // Clear memory. + t.Lookup = nil + runtime.GC() +} From b7f42dd40665ed8a0ef561b78a2344453e931847 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 14:37:13 +0330 Subject: [PATCH 058/775] Simplify adding tet4 to mesh --- render/tet4.go | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 6f57e4ecc..1a8a0c132 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -21,7 +21,6 @@ type MeshTet4 struct { T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. V []v3.Vec // Vertex buffer. All unique. Lookup map[[3]float64]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. - vCount uint32 // TODO: Remove? } func NewMeshTet4() *MeshTet4 { @@ -32,17 +31,13 @@ func NewMeshTet4() *MeshTet4 { } } -func (m *MeshTet4) Allocate(tetCount uint32) { - m.T = make([]uint32, tetCount*4) +func (m *MeshTet4) AddTet(a, b, c, d v3.Vec) { + // Index of current tetrahedron being added. + i := len(m.T) / 4 - // Just an optimization by experimenting. - // Affects the speed according to experiments. - m.V = make([]v3.Vec, tetCount/4*2) + // Make room for a new tetrahedron. + m.T = append(m.T, 0, 0, 0, 0) - m.Lookup = make(map[[3]float64]uint32, tetCount/4*2) -} - -func (m *MeshTet4) AddTet(i uint32, a, b, c, d v3.Vec) { // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf m.T[i*4], m.T[i*4+1], m.T[i*4+2], m.T[i*4+3] = m.AddVertex(a), m.AddVertex(b), m.AddVertex(c), m.AddVertex(d) @@ -54,14 +49,12 @@ func (m *MeshTet4) AddVertex(vert v3.Vec) uint32 { if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { return vertID } - if m.VertexCount() <= int(m.vCount) { - m.V = append(m.V, vert) - } else { - m.V[m.vCount] = vert - } - m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = m.vCount - m.vCount++ - return m.vCount - 1 + + m.V = append(m.V, vert) + + m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.VertexCount()) + + return uint32(m.VertexCount()) } func (m *MeshTet4) VertexCount() int { @@ -69,7 +62,6 @@ func (m *MeshTet4) VertexCount() int { } func (t *MeshTet4) Finalize() { - t.V = t.V[:t.vCount] // Clear memory. t.Lookup = nil runtime.GC() From 8b6a9b05fcd53704186dc80c1fdbf858e57dc420 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 14:54:59 +0330 Subject: [PATCH 059/775] More funcs for mesh --- render/tet4.go | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 1a8a0c132..6ac123663 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -31,19 +31,13 @@ func NewMeshTet4() *MeshTet4 { } } -func (m *MeshTet4) AddTet(a, b, c, d v3.Vec) { - // Index of current tetrahedron being added. - i := len(m.T) / 4 - - // Make room for a new tetrahedron. - m.T = append(m.T, 0, 0, 0, 0) - - // The node numbering should follow the convention of CalculiX. - // http://www.dhondt.de/ccx_2.20.pdf - m.T[i*4], m.T[i*4+1], m.T[i*4+2], m.T[i*4+3] = m.AddVertex(a), m.AddVertex(b), m.AddVertex(c), m.AddVertex(d) +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (m *MeshTet4) AddTet4(a, b, c, d v3.Vec) { + m.T = append(m.T, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) } -func (m *MeshTet4) AddVertex(vert v3.Vec) uint32 { +func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { // TODO: Binary insertion sort and search to eliminate extra allocation // TODO: Consider epsilon in comparison and use int (*100) for searching if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { @@ -52,17 +46,35 @@ func (m *MeshTet4) AddVertex(vert v3.Vec) uint32 { m.V = append(m.V, vert) - m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.VertexCount()) + m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.countVertex()) - return uint32(m.VertexCount()) + return uint32(m.countVertex()) } -func (m *MeshTet4) VertexCount() int { +func (m *MeshTet4) countVertex() int { return len(m.V) } +// To be called after adding all tetrahedra to the mesh. func (t *MeshTet4) Finalize() { // Clear memory. t.Lookup = nil runtime.GC() } + +// Number of tetrahedra on mesh. +func (m *MeshTet4) CountTet4() int { + return len(m.T) / 4 +} + +// Input from 0 to number of tetrahedra on mesh. +// Don't return error to increase performance. +func (m *MeshTet4) Tet4Indicies(i int) (uint32, uint32, uint32, uint32) { + return m.T[i*4], m.T[i*4+1], m.T[i*4+2], m.T[i*4+3] +} + +// Input from 0 to number of tetrahedra on mesh. +// Don't return error to increase performance. +func (m *MeshTet4) Tet4Vertices(i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { + return m.V[m.T[i*4]], m.V[m.T[i*4+1]], m.V[m.T[i*4+2]], m.V[m.T[i*4+3]] +} From ac01b82595df5f7ea0686d86be026d5daadd000c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 15:06:37 +0330 Subject: [PATCH 060/775] Low-level vertex buffer --- render/tet4.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 6ac123663..40af855ab 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -17,36 +17,37 @@ type Tet4 struct { // A sophisticated data structure for mesh is required to store tetrahedra. // The repeated nodes would be removed. // The element connectivity would be created with unique nodes. +// Keep it low-level to increase performance. Indicated by experiments. type MeshTet4 struct { - T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. - V []v3.Vec // Vertex buffer. All unique. - Lookup map[[3]float64]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. + T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron of (i, j, k, l). + V []float32 // Vertex buffer. Every 3 floats would correspond to a vertex of (x, y, z). + Lookup map[[3]float32]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. } func NewMeshTet4() *MeshTet4 { return &MeshTet4{ T: []uint32{}, - V: []v3.Vec{}, - Lookup: map[[3]float64]uint32{}, + V: []float32{}, + Lookup: map[[3]float32]uint32{}, } } // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) AddTet4(a, b, c, d v3.Vec) { +func (m *MeshTet4) AddTet4(a, b, c, d [3]float32) { m.T = append(m.T, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) } -func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { +func (m *MeshTet4) addVertex(vert [3]float32) uint32 { // TODO: Binary insertion sort and search to eliminate extra allocation // TODO: Consider epsilon in comparison and use int (*100) for searching - if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { + if vertID, ok := m.Lookup[vert]; ok { return vertID } - m.V = append(m.V, vert) + m.V = append(m.V, vert[0], vert[1], vert[2]) - m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.countVertex()) + m.Lookup[vert] = uint32(m.countVertex()) return uint32(m.countVertex()) } @@ -75,6 +76,9 @@ func (m *MeshTet4) Tet4Indicies(i int) (uint32, uint32, uint32, uint32) { // Input from 0 to number of tetrahedra on mesh. // Don't return error to increase performance. -func (m *MeshTet4) Tet4Vertices(i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { - return m.V[m.T[i*4]], m.V[m.T[i*4+1]], m.V[m.T[i*4+2]], m.V[m.T[i*4+3]] +func (m *MeshTet4) Tet4Vertices(i int) ([3]float32, [3]float32, [3]float32, [3]float32) { + return [3]float32{m.V[m.T[i*4]*3], m.V[m.T[i*4]*3+1], m.V[m.T[i*4]*3+2]}, + [3]float32{m.V[m.T[i*4+1]*3], m.V[m.T[i*4+1]*3+1], m.V[m.T[i*4+1]*3+2]}, + [3]float32{m.V[m.T[i*4+2]*3], m.V[m.T[i*4+2]*3+1], m.V[m.T[i*4+2]*3+2]}, + [3]float32{m.V[m.T[i*4+3]*3], m.V[m.T[i*4+3]*3+1], m.V[m.T[i*4+3]*3+2]} } From 0e7fc7405d820d6a65ea6ec297f200ccd7746d82 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 15:06:52 +0330 Subject: [PATCH 061/775] Revert "Low-level vertex buffer" This reverts commit ac01b82595df5f7ea0686d86be026d5daadd000c. --- render/tet4.go | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 40af855ab..6ac123663 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -17,37 +17,36 @@ type Tet4 struct { // A sophisticated data structure for mesh is required to store tetrahedra. // The repeated nodes would be removed. // The element connectivity would be created with unique nodes. -// Keep it low-level to increase performance. Indicated by experiments. type MeshTet4 struct { - T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron of (i, j, k, l). - V []float32 // Vertex buffer. Every 3 floats would correspond to a vertex of (x, y, z). - Lookup map[[3]float32]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. + T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. + V []v3.Vec // Vertex buffer. All unique. + Lookup map[[3]float64]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. } func NewMeshTet4() *MeshTet4 { return &MeshTet4{ T: []uint32{}, - V: []float32{}, - Lookup: map[[3]float32]uint32{}, + V: []v3.Vec{}, + Lookup: map[[3]float64]uint32{}, } } // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) AddTet4(a, b, c, d [3]float32) { +func (m *MeshTet4) AddTet4(a, b, c, d v3.Vec) { m.T = append(m.T, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) } -func (m *MeshTet4) addVertex(vert [3]float32) uint32 { +func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { // TODO: Binary insertion sort and search to eliminate extra allocation // TODO: Consider epsilon in comparison and use int (*100) for searching - if vertID, ok := m.Lookup[vert]; ok { + if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { return vertID } - m.V = append(m.V, vert[0], vert[1], vert[2]) + m.V = append(m.V, vert) - m.Lookup[vert] = uint32(m.countVertex()) + m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.countVertex()) return uint32(m.countVertex()) } @@ -76,9 +75,6 @@ func (m *MeshTet4) Tet4Indicies(i int) (uint32, uint32, uint32, uint32) { // Input from 0 to number of tetrahedra on mesh. // Don't return error to increase performance. -func (m *MeshTet4) Tet4Vertices(i int) ([3]float32, [3]float32, [3]float32, [3]float32) { - return [3]float32{m.V[m.T[i*4]*3], m.V[m.T[i*4]*3+1], m.V[m.T[i*4]*3+2]}, - [3]float32{m.V[m.T[i*4+1]*3], m.V[m.T[i*4+1]*3+1], m.V[m.T[i*4+1]*3+2]}, - [3]float32{m.V[m.T[i*4+2]*3], m.V[m.T[i*4+2]*3+1], m.V[m.T[i*4+2]*3+2]}, - [3]float32{m.V[m.T[i*4+3]*3], m.V[m.T[i*4+3]*3+1], m.V[m.T[i*4+3]*3+2]} +func (m *MeshTet4) Tet4Vertices(i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { + return m.V[m.T[i*4]], m.V[m.T[i*4+1]], m.V[m.T[i*4+2]], m.V[m.T[i*4+3]] } From 9a22ba781fcef8c219f6fba3727366234da45c8d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 15:09:20 +0330 Subject: [PATCH 062/775] Rename --- render/tet4.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 6ac123663..e6016ae54 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -46,12 +46,12 @@ func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { m.V = append(m.V, vert) - m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.countVertex()) + m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.vertexCount()) - return uint32(m.countVertex()) + return uint32(m.vertexCount()) } -func (m *MeshTet4) countVertex() int { +func (m *MeshTet4) vertexCount() int { return len(m.V) } @@ -63,7 +63,7 @@ func (t *MeshTet4) Finalize() { } // Number of tetrahedra on mesh. -func (m *MeshTet4) CountTet4() int { +func (m *MeshTet4) Tet4Count() int { return len(m.T) / 4 } From 54c0c79d0f9ccd5a9c4659468597d293cecb442f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 15:21:58 +0330 Subject: [PATCH 063/775] Return mesh rather than tetrahedra --- render/marchtet4.go | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index c19f2bb1f..5363a6578 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -10,34 +10,24 @@ import ( //----------------------------------------------------------------------------- -func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { +func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) *MeshTet4 { fmt.Printf("marching tetrahedra, bbox center: %v , step: %v\n", s.BoundingBox().Center(), step) - var tetrahedra []*Tet4 + m := NewMeshTet4() // Constant hard-coded tetrahedra vertices to develop and debug the output API. // https://cs.stackexchange.com/a/90011/67985 - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, - }) + + m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 0, Z: 1}, v3.Vec{X: 0, Y: 1, Z: 1}, v3.Vec{X: 1, Y: 1, Z: 1}) + m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 1, Z: 0}, v3.Vec{X: 0, Y: 1, Z: 1}, v3.Vec{X: 1, Y: 1, Z: 1}) + m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 0, Z: 1}, v3.Vec{X: 1, Y: 0, Z: 1}, v3.Vec{X: 1, Y: 1, Z: 1}) + m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 1, Y: 0, Z: 0}, v3.Vec{X: 1, Y: 0, Z: 1}, v3.Vec{X: 1, Y: 1, Z: 1}) + m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 1, Z: 0}, v3.Vec{X: 1, Y: 1, Z: 0}, v3.Vec{X: 1, Y: 1, Z: 1}) + m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 1, Y: 0, Z: 0}, v3.Vec{X: 1, Y: 1, Z: 0}, v3.Vec{X: 1, Y: 1, Z: 1}) + m.Finalize() // TODO: Logic. - return tetrahedra + return m } //----------------------------------------------------------------------------- From d517854be64c82b4b8b37d80add9b7469ba09b6c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 15:22:21 +0330 Subject: [PATCH 064/775] Revert "Return mesh rather than tetrahedra" This reverts commit 54c0c79d0f9ccd5a9c4659468597d293cecb442f. --- render/marchtet4.go | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index 5363a6578..c19f2bb1f 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -10,24 +10,34 @@ import ( //----------------------------------------------------------------------------- -func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) *MeshTet4 { +func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { fmt.Printf("marching tetrahedra, bbox center: %v , step: %v\n", s.BoundingBox().Center(), step) - m := NewMeshTet4() + var tetrahedra []*Tet4 // Constant hard-coded tetrahedra vertices to develop and debug the output API. // https://cs.stackexchange.com/a/90011/67985 - - m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 0, Z: 1}, v3.Vec{X: 0, Y: 1, Z: 1}, v3.Vec{X: 1, Y: 1, Z: 1}) - m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 1, Z: 0}, v3.Vec{X: 0, Y: 1, Z: 1}, v3.Vec{X: 1, Y: 1, Z: 1}) - m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 0, Z: 1}, v3.Vec{X: 1, Y: 0, Z: 1}, v3.Vec{X: 1, Y: 1, Z: 1}) - m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 1, Y: 0, Z: 0}, v3.Vec{X: 1, Y: 0, Z: 1}, v3.Vec{X: 1, Y: 1, Z: 1}) - m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 1, Z: 0}, v3.Vec{X: 1, Y: 1, Z: 0}, v3.Vec{X: 1, Y: 1, Z: 1}) - m.AddTet4(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 1, Y: 0, Z: 0}, v3.Vec{X: 1, Y: 1, Z: 0}, v3.Vec{X: 1, Y: 1, Z: 1}) - m.Finalize() + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, + }) // TODO: Logic. - return m + return tetrahedra } //----------------------------------------------------------------------------- From 4af83583617611c8b4a1f71dd659fbc3f7483c52 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 15:25:17 +0330 Subject: [PATCH 065/775] Delete the new mesh data structure --- render/tet4.go | 68 -------------------------------------------------- 1 file changed, 68 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index e6016ae54..355c37199 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -1,8 +1,6 @@ package render import ( - "runtime" - v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -12,69 +10,3 @@ import ( type Tet4 struct { V [4]v3.Vec } - -// A mesh of tetrahedra with 4 nodes. -// A sophisticated data structure for mesh is required to store tetrahedra. -// The repeated nodes would be removed. -// The element connectivity would be created with unique nodes. -type MeshTet4 struct { - T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. - V []v3.Vec // Vertex buffer. All unique. - Lookup map[[3]float64]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. -} - -func NewMeshTet4() *MeshTet4 { - return &MeshTet4{ - T: []uint32{}, - V: []v3.Vec{}, - Lookup: map[[3]float64]uint32{}, - } -} - -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) AddTet4(a, b, c, d v3.Vec) { - m.T = append(m.T, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) -} - -func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { - // TODO: Binary insertion sort and search to eliminate extra allocation - // TODO: Consider epsilon in comparison and use int (*100) for searching - if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { - return vertID - } - - m.V = append(m.V, vert) - - m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.vertexCount()) - - return uint32(m.vertexCount()) -} - -func (m *MeshTet4) vertexCount() int { - return len(m.V) -} - -// To be called after adding all tetrahedra to the mesh. -func (t *MeshTet4) Finalize() { - // Clear memory. - t.Lookup = nil - runtime.GC() -} - -// Number of tetrahedra on mesh. -func (m *MeshTet4) Tet4Count() int { - return len(m.T) / 4 -} - -// Input from 0 to number of tetrahedra on mesh. -// Don't return error to increase performance. -func (m *MeshTet4) Tet4Indicies(i int) (uint32, uint32, uint32, uint32) { - return m.T[i*4], m.T[i*4+1], m.T[i*4+2], m.T[i*4+3] -} - -// Input from 0 to number of tetrahedra on mesh. -// Don't return error to increase performance. -func (m *MeshTet4) Tet4Vertices(i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { - return m.V[m.T[i*4]], m.V[m.T[i*4+1]], m.V[m.T[i*4+2]], m.V[m.T[i*4+3]] -} From 3987a9f4639d046100efd015b284b0d7fd4c20a1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 15:49:15 +0330 Subject: [PATCH 066/775] Revert "Delete the new mesh data structure" This reverts commit 4af83583617611c8b4a1f71dd659fbc3f7483c52. --- render/tet4.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/render/tet4.go b/render/tet4.go index 355c37199..e6016ae54 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -1,6 +1,8 @@ package render import ( + "runtime" + v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -10,3 +12,69 @@ import ( type Tet4 struct { V [4]v3.Vec } + +// A mesh of tetrahedra with 4 nodes. +// A sophisticated data structure for mesh is required to store tetrahedra. +// The repeated nodes would be removed. +// The element connectivity would be created with unique nodes. +type MeshTet4 struct { + T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. + V []v3.Vec // Vertex buffer. All unique. + Lookup map[[3]float64]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. +} + +func NewMeshTet4() *MeshTet4 { + return &MeshTet4{ + T: []uint32{}, + V: []v3.Vec{}, + Lookup: map[[3]float64]uint32{}, + } +} + +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (m *MeshTet4) AddTet4(a, b, c, d v3.Vec) { + m.T = append(m.T, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) +} + +func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { + // TODO: Binary insertion sort and search to eliminate extra allocation + // TODO: Consider epsilon in comparison and use int (*100) for searching + if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { + return vertID + } + + m.V = append(m.V, vert) + + m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.vertexCount()) + + return uint32(m.vertexCount()) +} + +func (m *MeshTet4) vertexCount() int { + return len(m.V) +} + +// To be called after adding all tetrahedra to the mesh. +func (t *MeshTet4) Finalize() { + // Clear memory. + t.Lookup = nil + runtime.GC() +} + +// Number of tetrahedra on mesh. +func (m *MeshTet4) Tet4Count() int { + return len(m.T) / 4 +} + +// Input from 0 to number of tetrahedra on mesh. +// Don't return error to increase performance. +func (m *MeshTet4) Tet4Indicies(i int) (uint32, uint32, uint32, uint32) { + return m.T[i*4], m.T[i*4+1], m.T[i*4+2], m.T[i*4+3] +} + +// Input from 0 to number of tetrahedra on mesh. +// Don't return error to increase performance. +func (m *MeshTet4) Tet4Vertices(i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { + return m.V[m.T[i*4]], m.V[m.T[i*4+1]], m.V[m.T[i*4+2]], m.V[m.T[i*4+3]] +} From 26483e8a96319e275577de6f33f59d2fa05b53df Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 16:01:21 +0330 Subject: [PATCH 067/775] Rename --- examples/finite_elements/main.go | 2 +- render/inp.go | 4 ++-- render/render.go | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 2b0e9b049..c08fb1bc5 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -33,5 +33,5 @@ func main() { // Render SDF3 to finite elements. // Output file can be used by ABAQUS or CalculiX. - render.ToFE(teapotSdf, "teapot.inp", render.NewMarchingTetrahedraUniform(200)) + render.ToInpTet4(teapotSdf, "teapot.inp", render.NewMarchingTetrahedraUniform(200)) } diff --git a/render/inp.go b/render/inp.go index 6dbbb30ef..e207a951a 100644 --- a/render/inp.go +++ b/render/inp.go @@ -13,8 +13,8 @@ import ( //----------------------------------------------------------------------------- -// writeFE writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. -func writeFE(wg *sync.WaitGroup, path string) (chan<- []*Tet4, error) { +// writeInpTet4 writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. +func writeInpTet4(wg *sync.WaitGroup, path string) (chan<- []*Tet4, error) { f, err := os.Create(path) if err != nil { return nil, err diff --git a/render/render.go b/render/render.go index ebed1a7b0..16ec00c91 100644 --- a/render/render.go +++ b/render/render.go @@ -59,9 +59,9 @@ func ToTriangles( //----------------------------------------------------------------------------- -// ToFE renders an SDF3 to finite elements in the shape of tetrahedra. -// Tetrahedra would then be written to an ABAQUS or CalculiX input file. -func ToFE( +// ToInpTet4 renders an SDF3 to finite elements in the shape of tetrahedra. +// Tetrahedra would then be written to an ABAQUS or CalculiX `inp` file. +func ToInpTet4( s sdf.SDF3, // sdf3 to render path string, // path to filename r RenderFE, // rendering method @@ -69,7 +69,7 @@ func ToFE( fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) // write the tetrahedra to an ABAQUS or CalculiX file var wg sync.WaitGroup - output, err := writeFE(&wg, path) + output, err := writeInpTet4(&wg, path) if err != nil { fmt.Printf("%s", err) return From ca4e64e594562b70230a90d1487bdafc4c435090 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 16:23:38 +0330 Subject: [PATCH 068/775] Change design: new func to write mesh to `inp` --- render/inp.go | 82 +++----------------------------------------------- render/tet4.go | 64 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 78 deletions(-) diff --git a/render/inp.go b/render/inp.go index e207a951a..013299525 100644 --- a/render/inp.go +++ b/render/inp.go @@ -1,10 +1,7 @@ package render import ( - "fmt" - "os" "sync" - "time" ) //----------------------------------------------------------------------------- @@ -15,21 +12,6 @@ import ( // writeInpTet4 writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. func writeInpTet4(wg *sync.WaitGroup, path string) (chan<- []*Tet4, error) { - f, err := os.Create(path) - if err != nil { - return nil, err - } - - _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") - if err != nil { - return nil, err - } - - _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") - if err != nil { - return nil, err - } - // External code writes tetrahedra to this channel. // This goroutine reads the channel and writes tetrahedra to the file. c := make(chan []*Tet4) @@ -37,73 +19,17 @@ func writeInpTet4(wg *sync.WaitGroup, path string) (chan<- []*Tet4, error) { wg.Add(1) go func() { defer wg.Done() - defer f.Close() - _, err = f.WriteString("*NODE\n") - if err != nil { - fmt.Printf("%s\n", err) - return - } + m := NewMeshTet4() + defer m.WriteInp(path) - var nodeCount uint32 = 1 // Right, starts with 1 - var tetCount uint32 = 0 // - - // read tetrahedra from the channel and write them to the file + // read finite elements from the channel and handle them for ts := range c { for _, t := range ts { - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[0].X), float32(t.V[0].Y), float32(t.V[0].Z))) - if err != nil { - fmt.Printf("%s\n", err) - return - } - nodeCount++ - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[1].X), float32(t.V[1].Y), float32(t.V[1].Z))) - if err != nil { - fmt.Printf("%s\n", err) - return - } - nodeCount++ - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[2].X), float32(t.V[2].Y), float32(t.V[2].Z))) - if err != nil { - fmt.Printf("%s\n", err) - return - } - nodeCount++ - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", nodeCount, float32(t.V[3].X), float32(t.V[3].Y), float32(t.V[3].Z))) - if err != nil { - fmt.Printf("%s\n", err) - return - } - nodeCount++ - tetCount++ + m.AddTet4(t.V[0], t.V[1], t.V[2], t.V[3]) } } - - _, err = f.WriteString("*ELEMENT, TYPE=C3D4, ELSET=Eall\n") - if err != nil { - fmt.Printf("%s\n", err) - return - } - - var eleId uint32 = 1 // Right, start with 1 - var nodeIdx uint32 = 0 // Will be incremented. So will be starting from 1. - - for i := 0; i < int(tetCount); i++ { - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleId, inc(&nodeIdx), inc(&nodeIdx), inc(&nodeIdx), inc(&nodeIdx))) - if err != nil { - fmt.Printf("%s\n", err) - return - } - eleId++ - } }() return c, nil } - -// To be able to increment values in-place. -// https://stackoverflow.com/a/56015749/3405291 -func inc(i *uint32) uint32 { - *i++ - return *i -} diff --git a/render/tet4.go b/render/tet4.go index e6016ae54..0f0b06b39 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -1,7 +1,10 @@ package render import ( + "fmt" + "os" "runtime" + "time" v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -55,6 +58,10 @@ func (m *MeshTet4) vertexCount() int { return len(m.V) } +func (m *MeshTet4) vertex(i int) v3.Vec { + return m.V[i] +} + // To be called after adding all tetrahedra to the mesh. func (t *MeshTet4) Finalize() { // Clear memory. @@ -78,3 +85,60 @@ func (m *MeshTet4) Tet4Indicies(i int) (uint32, uint32, uint32, uint32) { func (m *MeshTet4) Tet4Vertices(i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { return m.V[m.T[i*4]], m.V[m.T[i*4+1]], m.V[m.T[i*4+2]], m.V[m.T[i*4+3]] } + +// Write mesh to ABAQUS or CalculiX `inp` file. +func (m *MeshTet4) WriteInp(path string) error { + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + + // Write headers. + + _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") + if err != nil { + return err + } + + _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") + if err != nil { + return err + } + + // Write nodes. + + _, err = f.WriteString("*NODE\n") + if err != nil { + return err + } + + var node v3.Vec + for i := 0; i < m.vertexCount(); i++ { + node = m.vertex(i) + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", i+1, float32(node.X), float32(node.Y), float32(node.Z))) + if err != nil { + return err + } + } + + // Write elements. + + _, err = f.WriteString("*ELEMENT, TYPE=C3D4, ELSET=Eall\n") + if err != nil { + return err + } + + var idx0, idx1, idx2, idx3 uint32 + for i := 0; i < m.Tet4Count(); i++ { + idx0, idx1, idx2, idx3 = m.Tet4Indicies(i) + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", i+1, idx0+1, idx1+1, idx2+1, idx3+1)) + if err != nil { + return err + } + } + + return nil +} From 6c7cdcd9eaf3ae44e16d9368dfe7b478501f9f3d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 16:34:47 +0330 Subject: [PATCH 069/775] Fix bug: index of new vertex --- render/tet4.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 0f0b06b39..e22d3ff90 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -44,14 +44,18 @@ func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { // TODO: Binary insertion sort and search to eliminate extra allocation // TODO: Consider epsilon in comparison and use int (*100) for searching if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { + // Vertex already exists. It's repeated. return vertID } + // Vertex is new, so append it. m.V = append(m.V, vert) - m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.vertexCount()) + // Store index of the appended vertex. + m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.vertexCount() - 1) - return uint32(m.vertexCount()) + // Return index of the appended vertex. + return uint32(m.vertexCount() - 1) } func (m *MeshTet4) vertexCount() int { From c4abc25196bb6f6674e7bd55005eabafdf459604 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 16:40:08 +0330 Subject: [PATCH 070/775] Finalize after adding all tetrahedra --- render/inp.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/render/inp.go b/render/inp.go index 013299525..1d18ee0b9 100644 --- a/render/inp.go +++ b/render/inp.go @@ -29,6 +29,8 @@ func writeInpTet4(wg *sync.WaitGroup, path string) (chan<- []*Tet4, error) { m.AddTet4(t.V[0], t.V[1], t.V[2], t.V[3]) } } + + m.Finalize() }() return c, nil From 2f262ff18a77017a7d56de5eab657d554db62d0e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 16:42:48 +0330 Subject: [PATCH 071/775] Comment --- render/tet4.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/tet4.go b/render/tet4.go index e22d3ff90..82821b1fb 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -21,7 +21,7 @@ type Tet4 struct { // The repeated nodes would be removed. // The element connectivity would be created with unique nodes. type MeshTet4 struct { - T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. + T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. Low-level for performance. V []v3.Vec // Vertex buffer. All unique. Lookup map[[3]float64]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. } From a580fc038736dc16435856042e3720d76e0e93b6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 16:45:58 +0330 Subject: [PATCH 072/775] Comment --- render/render.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/render.go b/render/render.go index 16ec00c91..9a40757ad 100644 --- a/render/render.go +++ b/render/render.go @@ -67,7 +67,7 @@ func ToInpTet4( r RenderFE, // rendering method ) { fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) - // write the tetrahedra to an ABAQUS or CalculiX file + // write the tetrahedra to an ABAQUS or CalculiX `inp` file var wg sync.WaitGroup output, err := writeInpTet4(&wg, path) if err != nil { @@ -76,7 +76,7 @@ func ToInpTet4( } // run the renderer r.Render(s, output) - // stop the FE writer reading on the channel + // stop the writer reading on the channel close(output) // wait for the file write to complete wg.Wait() From 1cb70fa9423ba18afdd9bda7d588a56c81ee4bb2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 16:57:17 +0330 Subject: [PATCH 073/775] Rename --- render/render.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/render/render.go b/render/render.go index 9a40757ad..a6a28b648 100644 --- a/render/render.go +++ b/render/render.go @@ -29,9 +29,9 @@ type Render2 interface { Info(s sdf.SDF2) string } -// RenderFE renders a finite element mesh over the bounding volume of an sdf3. +// RenderTet4 renders a finite element mesh over the bounding volume of an sdf3. // Finite elements are in the shape of tetrahedra. -type RenderFE interface { +type RenderTet4 interface { Render(sdf3 sdf.SDF3, output chan<- []*Tet4) Info(sdf3 sdf.SDF3) string } @@ -64,7 +64,7 @@ func ToTriangles( func ToInpTet4( s sdf.SDF3, // sdf3 to render path string, // path to filename - r RenderFE, // rendering method + r RenderTet4, // rendering method ) { fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) // write the tetrahedra to an ABAQUS or CalculiX `inp` file From dc0efa39d1386ce6bf111e3f2aed135ec6888a53 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 16:58:29 +0330 Subject: [PATCH 074/775] Comment --- render/render.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/render.go b/render/render.go index a6a28b648..7214e52b6 100644 --- a/render/render.go +++ b/render/render.go @@ -30,7 +30,7 @@ type Render2 interface { } // RenderTet4 renders a finite element mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of tetrahedra. +// Finite elements are in the shape of tetrahedra, each with 4 nodes. type RenderTet4 interface { Render(sdf3 sdf.SDF3, output chan<- []*Tet4) Info(sdf3 sdf.SDF3) string From 065e5429655a9bf6dce1ac539b14d5aa36928d6f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 17:03:27 +0330 Subject: [PATCH 075/775] Rename: clear --- examples/finite_elements/main.go | 2 +- render/marchtet4.go | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c08fb1bc5..181f8a043 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -33,5 +33,5 @@ func main() { // Render SDF3 to finite elements. // Output file can be used by ABAQUS or CalculiX. - render.ToInpTet4(teapotSdf, "teapot.inp", render.NewMarchingTetrahedraUniform(200)) + render.ToInpTet4(teapotSdf, "teapot.inp", render.NewMarchingTet4Uniform(200)) } diff --git a/render/marchtet4.go b/render/marchtet4.go index c19f2bb1f..78f6a6c34 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -10,7 +10,7 @@ import ( //----------------------------------------------------------------------------- -func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { +func marchingTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { fmt.Printf("marching tetrahedra, bbox center: %v , step: %v\n", s.BoundingBox().Center(), step) var tetrahedra []*Tet4 @@ -42,20 +42,20 @@ func marchingTetrahedra(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { //----------------------------------------------------------------------------- -// MarchingTetrahedraUniform renders using marching Tetrahedra with uniform space sampling. -type MarchingTetrahedraUniform struct { +// MarchingTet4Uniform renders using marching Tetrahedra with uniform space sampling. +type MarchingTet4Uniform struct { meshCells int // number of cells on the longest axis of bounding box. e.g 200 } -// NewMarchingTetrahedraUniform returns a RenderFE object. -func NewMarchingTetrahedraUniform(meshCells int) *MarchingTetrahedraUniform { - return &MarchingTetrahedraUniform{ +// NewMarchingTet4Uniform returns a RenderFE object. +func NewMarchingTet4Uniform(meshCells int) *MarchingTet4Uniform { + return &MarchingTet4Uniform{ meshCells: meshCells, } } // Info returns a string describing the rendered volume. -func (r *MarchingTetrahedraUniform) Info(s sdf.SDF3) string { +func (r *MarchingTet4Uniform) Info(s sdf.SDF3) string { bb0 := s.BoundingBox() bb0Size := bb0.Size() meshInc := bb0Size.MaxComponent() / float64(r.meshCells) @@ -67,7 +67,7 @@ func (r *MarchingTetrahedraUniform) Info(s sdf.SDF3) string { // Render produces a finite elements mesh over the bounding volume of an sdf3. // Finite elements are in the shape of tetrahedra. -func (r *MarchingTetrahedraUniform) Render(s sdf.SDF3, output chan<- []*Tet4) { +func (r *MarchingTet4Uniform) Render(s sdf.SDF3, output chan<- []*Tet4) { // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() @@ -76,7 +76,7 @@ func (r *MarchingTetrahedraUniform) Render(s sdf.SDF3, output chan<- []*Tet4) { bb1Size = bb1Size.Ceil().AddScalar(1) bb1Size = bb1Size.MulScalar(meshInc) bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingTetrahedra(s, bb, meshInc) + output <- marchingTet4(s, bb, meshInc) } //----------------------------------------------------------------------------- From 45560f61e69d6e05a3dc1faec3a7d5abd3019036 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 25 Feb 2023 17:05:01 +0330 Subject: [PATCH 076/775] Comment --- examples/finite_elements/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 181f8a043..91ffcca0b 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -1,7 +1,8 @@ //----------------------------------------------------------------------------- /* -Finite elements - tetrahedra - from triangle mesh. +Finite elements from triangle mesh. +Output `inp` file is consumable by ABAQUS or CalculiX. */ //----------------------------------------------------------------------------- From c8a5f993b371361b0e58c5ade9e77d1b33c581c7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 11:44:41 +0330 Subject: [PATCH 077/775] Store finite elements by their layer on Z axis --- render/inp.go | 6 ++-- render/marchtet4.go | 25 +++++++++---- render/render.go | 4 ++- render/tet4.go | 85 +++++++++++++++++++++++++++++++++------------ 4 files changed, 87 insertions(+), 33 deletions(-) diff --git a/render/inp.go b/render/inp.go index 1d18ee0b9..69083397b 100644 --- a/render/inp.go +++ b/render/inp.go @@ -11,7 +11,7 @@ import ( //----------------------------------------------------------------------------- // writeInpTet4 writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. -func writeInpTet4(wg *sync.WaitGroup, path string) (chan<- []*Tet4, error) { +func writeInpTet4(wg *sync.WaitGroup, path string, layerCount int) (chan<- []*Tet4, error) { // External code writes tetrahedra to this channel. // This goroutine reads the channel and writes tetrahedra to the file. c := make(chan []*Tet4) @@ -20,13 +20,13 @@ func writeInpTet4(wg *sync.WaitGroup, path string) (chan<- []*Tet4, error) { go func() { defer wg.Done() - m := NewMeshTet4() + m := NewMeshTet4(layerCount) defer m.WriteInp(path) // read finite elements from the channel and handle them for ts := range c { for _, t := range ts { - m.AddTet4(t.V[0], t.V[1], t.V[2], t.V[3]) + m.AddTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) } } diff --git a/render/marchtet4.go b/render/marchtet4.go index 78f6a6c34..c4bc5d18e 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -17,22 +17,28 @@ func marchingTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { // Constant hard-coded tetrahedra vertices to develop and debug the output API. // https://cs.stackexchange.com/a/90011/67985 tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, + layer: 0, }) tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, + layer: 0, }) tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, + layer: 0, }) tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, + layer: 0, }) tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, + layer: 0, }) tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, + V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, + layer: 0, }) // TODO: Logic. @@ -56,13 +62,18 @@ func NewMarchingTet4Uniform(meshCells int) *MarchingTet4Uniform { // Info returns a string describing the rendered volume. func (r *MarchingTet4Uniform) Info(s sdf.SDF3) string { + cellsX, cellsY, cellsZ := r.Cells(s) + return fmt.Sprintf("%dx%dx%d", cellsX, cellsY, cellsZ) +} + +func (r *MarchingTet4Uniform) Cells(s sdf.SDF3) (int, int, int) { bb0 := s.BoundingBox() bb0Size := bb0.Size() meshInc := bb0Size.MaxComponent() / float64(r.meshCells) bb1Size := bb0Size.DivScalar(meshInc) bb1Size = bb1Size.Ceil().AddScalar(1) cells := conv.V3ToV3i(bb1Size) - return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) + return cells.X, cells.Y, cells.Z } // Render produces a finite elements mesh over the bounding volume of an sdf3. diff --git a/render/render.go b/render/render.go index 7214e52b6..6bb423022 100644 --- a/render/render.go +++ b/render/render.go @@ -34,6 +34,7 @@ type Render2 interface { type RenderTet4 interface { Render(sdf3 sdf.SDF3, output chan<- []*Tet4) Info(sdf3 sdf.SDF3) string + Cells(sdf3 sdf.SDF3) (int, int, int) } //----------------------------------------------------------------------------- @@ -69,7 +70,8 @@ func ToInpTet4( fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) // write the tetrahedra to an ABAQUS or CalculiX `inp` file var wg sync.WaitGroup - output, err := writeInpTet4(&wg, path) + _, _, layerCount := r.Cells(s) + output, err := writeInpTet4(&wg, path, layerCount) if err != nil { fmt.Printf("%s", err) return diff --git a/render/tet4.go b/render/tet4.go index 82821b1fb..37dc355d1 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -13,7 +13,13 @@ import ( // It's a kind of finite element, FE. // https://en.wikipedia.org/wiki/Tetrahedron type Tet4 struct { + // Coordinates of 4 corner nodes or vertices. V [4]v3.Vec + // The layer to which tetrahedron belongs. Layers are along Z axis. + // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store layer along Z axis. + // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. + // Sampling/marching algorithm is expected to generate finite elements along the Z axis. + layer int } // A mesh of tetrahedra with 4 nodes. @@ -21,23 +27,38 @@ type Tet4 struct { // The repeated nodes would be removed. // The element connectivity would be created with unique nodes. type MeshTet4 struct { - T []uint32 // Index buffer. Every 4 indices would correspond to a tetrahedron. Low-level for performance. - V []v3.Vec // Vertex buffer. All unique. - Lookup map[[3]float64]uint32 // Used to avoid repeating vertices when adding a new tetrahedron. + // Index buffer. + // Every 4 indices would correspond to a tetrahedron. Low-level for performance. + // Tetrahedra are stored by their layer on Z axis. + T [][]uint32 + // Vertex buffer. + // All coordinates are unique. + V []v3.Vec + // Used to avoid repeating vertices when adding a new tetrahedron. + Lookup map[[3]float64]uint32 } -func NewMeshTet4() *MeshTet4 { - return &MeshTet4{ - T: []uint32{}, +func NewMeshTet4(layerCount int) *MeshTet4 { + t := &MeshTet4{ + T: nil, V: []v3.Vec{}, Lookup: map[[3]float64]uint32{}, } + + // Initialize. + t.T = make([][]uint32, layerCount) + for l := 0; l < layerCount; l++ { + t.T[l] = make([]uint32, 0) + } + + return t } +// Layer number and 4 nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) AddTet4(a, b, c, d v3.Vec) { - m.T = append(m.T, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) +func (m *MeshTet4) AddTet4(l int, a, b, c, d v3.Vec) { + m.T[l] = append(m.T[l], m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) } func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { @@ -73,21 +94,39 @@ func (t *MeshTet4) Finalize() { runtime.GC() } -// Number of tetrahedra on mesh. +// Number of layers along the Z axis. +func (m *MeshTet4) LayerCount() int { + return len(m.T) +} + +// Number of tetrahedra on a layer. +func (m *MeshTet4) Tet4CountOnLayer(l int) int { + return len(m.T[l]) +} + +// Number of tetrahedra for all layers. func (m *MeshTet4) Tet4Count() int { - return len(m.T) / 4 + var count int + for _, t := range m.T { + count += len(t) + } + return count } -// Input from 0 to number of tetrahedra on mesh. +// Layer number is input. +// Tetrahedron index on layer is input. +// Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) Tet4Indicies(i int) (uint32, uint32, uint32, uint32) { - return m.T[i*4], m.T[i*4+1], m.T[i*4+2], m.T[i*4+3] +func (m *MeshTet4) Tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { + return m.T[l][i*4], m.T[l][i*4+1], m.T[l][i*4+2], m.T[l][i*4+3] } -// Input from 0 to number of tetrahedra on mesh. +// Layer number is input. +// Tetrahedron index on layer is input. +// Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) Tet4Vertices(i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { - return m.V[m.T[i*4]], m.V[m.T[i*4+1]], m.V[m.T[i*4+2]], m.V[m.T[i*4+3]] +func (m *MeshTet4) Tet4Vertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { + return m.V[m.T[l][i*4]], m.V[m.T[l][i*4+1]], m.V[m.T[l][i*4+2]], m.V[m.T[l][i*4+3]] } // Write mesh to ABAQUS or CalculiX `inp` file. @@ -135,12 +174,14 @@ func (m *MeshTet4) WriteInp(path string) error { } var idx0, idx1, idx2, idx3 uint32 - for i := 0; i < m.Tet4Count(); i++ { - idx0, idx1, idx2, idx3 = m.Tet4Indicies(i) - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", i+1, idx0+1, idx1+1, idx2+1, idx3+1)) - if err != nil { - return err + for l := 0; l < m.LayerCount(); l++ { + for i := 0; i < m.Tet4CountOnLayer(l); i++ { + idx0, idx1, idx2, idx3 = m.Tet4Indicies(l, i) + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", i+1, idx0+1, idx1+1, idx2+1, idx3+1)) + if err != nil { + return err + } } } From 0268ba33b1ccb69708e63c452a7d5072e96ddaff Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 12:38:54 +0330 Subject: [PATCH 078/775] Fix bug: divide by 4 --- render/tet4.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 37dc355d1..99db694e2 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -101,14 +101,14 @@ func (m *MeshTet4) LayerCount() int { // Number of tetrahedra on a layer. func (m *MeshTet4) Tet4CountOnLayer(l int) int { - return len(m.T[l]) + return len(m.T[l]) / 4 } // Number of tetrahedra for all layers. func (m *MeshTet4) Tet4Count() int { var count int for _, t := range m.T { - count += len(t) + count += len(t) / 4 } return count } From e1ef49c85348e1b2975718c757c8d5bca6c586fa Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 12:52:16 +0330 Subject: [PATCH 079/775] Fix bug --- render/marchtet4.go | 82 +++++++++++++++++++++++++++------------------ render/render.go | 6 ++-- 2 files changed, 53 insertions(+), 35 deletions(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index c4bc5d18e..ed4c0c0c6 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -11,35 +11,45 @@ import ( //----------------------------------------------------------------------------- func marchingTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { - fmt.Printf("marching tetrahedra, bbox center: %v , step: %v\n", s.BoundingBox().Center(), step) + var tetrahedra []*Tet4 - // Constant hard-coded tetrahedra vertices to develop and debug the output API. - // https://cs.stackexchange.com/a/90011/67985 - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, - layer: 0, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 0, Y: 1, Z: 1}, {X: 1, Y: 1, Z: 1}}, - layer: 0, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 0, Z: 1}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, - layer: 0, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 1}, {X: 1, Y: 1, Z: 1}}, - layer: 0, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 0, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, - layer: 0, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: 0}, {X: 1, Y: 0, Z: 0}, {X: 1, Y: 1, Z: 0}, {X: 1, Y: 1, Z: 1}}, - layer: 0, - }) + size := box.Size() + steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) + + _, _, nz := steps.X, steps.Y, steps.Z + + for z := 0; z < nz; z++ { + + h := float64(z) + + // Constant hard-coded tetrahedra vertices to develop and debug the output API. + // https://cs.stackexchange.com/a/90011/67985 + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 0, Y: 0, Z: h + 1}, {X: 0, Y: 1, Z: h + 1}, {X: 1, Y: 1, Z: h + 1}}, + layer: z, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 0, Y: 1, Z: h}, {X: 0, Y: 1, Z: h + 1}, {X: 1, Y: 1, Z: h + 1}}, + layer: z, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 0, Y: 0, Z: h + 1}, {X: 1, Y: 0, Z: h + 1}, {X: 1, Y: 1, Z: h + 1}}, + layer: z, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 1, Y: 0, Z: h}, {X: 1, Y: 0, Z: h + 1}, {X: 1, Y: 1, Z: h + 1}}, + layer: z, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 0, Y: 1, Z: h}, {X: 1, Y: 1, Z: h}, {X: 1, Y: 1, Z: h + 1}}, + layer: z, + }) + tetrahedra = append(tetrahedra, &Tet4{ + V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 1, Y: 0, Z: h}, {X: 1, Y: 1, Z: h}, {X: 1, Y: 1, Z: h + 1}}, + layer: z, + }) + } // TODO: Logic. @@ -62,18 +72,26 @@ func NewMarchingTet4Uniform(meshCells int) *MarchingTet4Uniform { // Info returns a string describing the rendered volume. func (r *MarchingTet4Uniform) Info(s sdf.SDF3) string { - cellsX, cellsY, cellsZ := r.Cells(s) - return fmt.Sprintf("%dx%dx%d", cellsX, cellsY, cellsZ) + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + cells := conv.V3ToV3i(bb1Size) + return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) } -func (r *MarchingTet4Uniform) Cells(s sdf.SDF3) (int, int, int) { +func (r *MarchingTet4Uniform) LayerCounts(s sdf.SDF3) (int, int, int) { bb0 := s.BoundingBox() bb0Size := bb0.Size() meshInc := bb0Size.MaxComponent() / float64(r.meshCells) bb1Size := bb0Size.DivScalar(meshInc) bb1Size = bb1Size.Ceil().AddScalar(1) - cells := conv.V3ToV3i(bb1Size) - return cells.X, cells.Y, cells.Z + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + size := bb.Size() + steps := conv.V3ToV3i(size.DivScalar(meshInc).Ceil()) + return steps.X, steps.Y, steps.Z } // Render produces a finite elements mesh over the bounding volume of an sdf3. diff --git a/render/render.go b/render/render.go index 6bb423022..0f3abde2a 100644 --- a/render/render.go +++ b/render/render.go @@ -34,7 +34,7 @@ type Render2 interface { type RenderTet4 interface { Render(sdf3 sdf.SDF3, output chan<- []*Tet4) Info(sdf3 sdf.SDF3) string - Cells(sdf3 sdf.SDF3) (int, int, int) + LayerCounts(sdf3 sdf.SDF3) (int, int, int) } //----------------------------------------------------------------------------- @@ -70,8 +70,8 @@ func ToInpTet4( fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) // write the tetrahedra to an ABAQUS or CalculiX `inp` file var wg sync.WaitGroup - _, _, layerCount := r.Cells(s) - output, err := writeInpTet4(&wg, path, layerCount) + _, _, layerCountZ := r.LayerCounts(s) + output, err := writeInpTet4(&wg, path, layerCountZ) if err != nil { fmt.Printf("%s", err) return From 32aa868b37ea8e53877d01c537562406fb2a25f0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 13:03:00 +0330 Subject: [PATCH 080/775] Fix bug: element ID --- render/tet4.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/render/tet4.go b/render/tet4.go index 99db694e2..54b38cecd 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -173,15 +173,17 @@ func (m *MeshTet4) WriteInp(path string) error { return err } + var eleID uint32 var idx0, idx1, idx2, idx3 uint32 for l := 0; l < m.LayerCount(); l++ { for i := 0; i < m.Tet4CountOnLayer(l); i++ { idx0, idx1, idx2, idx3 = m.Tet4Indicies(l, i) // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", i+1, idx0+1, idx1+1, idx2+1, idx3+1)) + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, idx0+1, idx1+1, idx2+1, idx3+1)) if err != nil { return err } + eleID++ } } From 908027f45ff7ef60b13d173a3228fff17963706b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 13:07:07 +0330 Subject: [PATCH 081/775] Rename --- render/tet4.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 54b38cecd..b29b604be 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -174,12 +174,12 @@ func (m *MeshTet4) WriteInp(path string) error { } var eleID uint32 - var idx0, idx1, idx2, idx3 uint32 + var nodeID0, nodeID1, nodeID2, nodeID3 uint32 for l := 0; l < m.LayerCount(); l++ { for i := 0; i < m.Tet4CountOnLayer(l); i++ { - idx0, idx1, idx2, idx3 = m.Tet4Indicies(l, i) + nodeID0, nodeID1, nodeID2, nodeID3 = m.Tet4Indicies(l, i) // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, idx0+1, idx1+1, idx2+1, idx3+1)) + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, nodeID0+1, nodeID1+1, nodeID2+1, nodeID3+1)) if err != nil { return err } From 3df51380f600409eeb3da27e886fd7a53d30f148 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 13:14:00 +0330 Subject: [PATCH 082/775] Comment --- render/marchtet4.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/marchtet4.go b/render/marchtet4.go index ed4c0c0c6..ea2402c70 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -81,6 +81,7 @@ func (r *MarchingTet4Uniform) Info(s sdf.SDF3) string { return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) } +// To get the layer counts which are consistent with loops of marching algorithm. func (r *MarchingTet4Uniform) LayerCounts(s sdf.SDF3) (int, int, int) { bb0 := s.BoundingBox() bb0Size := bb0.Size() From e0410616c2883dca8b2870193c0ee9073b99ff9a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 13:20:49 +0330 Subject: [PATCH 083/775] Log of layer counts --- render/render.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/render/render.go b/render/render.go index 0f3abde2a..a4b059bf4 100644 --- a/render/render.go +++ b/render/render.go @@ -70,7 +70,8 @@ func ToInpTet4( fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) // write the tetrahedra to an ABAQUS or CalculiX `inp` file var wg sync.WaitGroup - _, _, layerCountZ := r.LayerCounts(s) + layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) + fmt.Printf("layer counts of marching are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) output, err := writeInpTet4(&wg, path, layerCountZ) if err != nil { fmt.Printf("%s", err) From 609d706d4eea41b6d64af9ea798c9c480448ef8a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 13:48:32 +0330 Subject: [PATCH 084/775] New func to get finite elements on specific layers --- render/tet4.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/render/tet4.go b/render/tet4.go index b29b604be..eb090989b 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -189,3 +189,70 @@ func (m *MeshTet4) WriteInp(path string) error { return nil } + +// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { + if 0 < layerStart && layerStart < layerEnd && layerEnd < m.LayerCount() { + // Good. + } else { + return fmt.Errorf("start or end layer is beyond range") + } + + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + + // Write headers. + + _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") + if err != nil { + return err + } + + _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") + if err != nil { + return err + } + + // Write nodes. + + _, err = f.WriteString("*NODE\n") + if err != nil { + return err + } + + var node v3.Vec + for i := 0; i < m.vertexCount(); i++ { + node = m.vertex(i) + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", i+1, float32(node.X), float32(node.Y), float32(node.Z))) + if err != nil { + return err + } + } + + // Write elements. + + _, err = f.WriteString("*ELEMENT, TYPE=C3D4, ELSET=Eall\n") + if err != nil { + return err + } + + var eleID uint32 + var nodeID0, nodeID1, nodeID2, nodeID3 uint32 + for l := layerStart; l < layerEnd; l++ { + for i := 0; i < m.Tet4CountOnLayer(l); i++ { + nodeID0, nodeID1, nodeID2, nodeID3 = m.Tet4Indicies(l, i) + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, nodeID0+1, nodeID1+1, nodeID2+1, nodeID3+1)) + if err != nil { + return err + } + eleID++ + } + } + + return nil +} From 166f4f9b05aa60f9cae567cd3746cec1b9bb3236 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 13:57:23 +0330 Subject: [PATCH 085/775] Single responsibility principle --- render/tet4.go | 62 ++++---------------------------------------------- 1 file changed, 4 insertions(+), 58 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index eb090989b..e2e7a200e 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -131,68 +131,14 @@ func (m *MeshTet4) Tet4Vertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { // Write mesh to ABAQUS or CalculiX `inp` file. func (m *MeshTet4) WriteInp(path string) error { - f, err := os.Create(path) - if err != nil { - return err - } - defer f.Close() - - // Write headers. - - _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") - if err != nil { - return err - } - - _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") - if err != nil { - return err - } - - // Write nodes. - - _, err = f.WriteString("*NODE\n") - if err != nil { - return err - } - - var node v3.Vec - for i := 0; i < m.vertexCount(); i++ { - node = m.vertex(i) - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", i+1, float32(node.X), float32(node.Y), float32(node.Z))) - if err != nil { - return err - } - } - - // Write elements. - - _, err = f.WriteString("*ELEMENT, TYPE=C3D4, ELSET=Eall\n") - if err != nil { - return err - } - - var eleID uint32 - var nodeID0, nodeID1, nodeID2, nodeID3 uint32 - for l := 0; l < m.LayerCount(); l++ { - for i := 0; i < m.Tet4CountOnLayer(l); i++ { - nodeID0, nodeID1, nodeID2, nodeID3 = m.Tet4Indicies(l, i) - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, nodeID0+1, nodeID1+1, nodeID2+1, nodeID3+1)) - if err != nil { - return err - } - eleID++ - } - } - - return nil + return m.WriteInpLayers(path, 0, m.LayerCount()) } // Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +// Result would include start layer. +// Result would exclude end layer. func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { - if 0 < layerStart && layerStart < layerEnd && layerEnd < m.LayerCount() { + if 0 <= layerStart && layerStart < layerEnd && layerEnd <= m.LayerCount() { // Good. } else { return fmt.Errorf("start or end layer is beyond range") From 6d364fc255b9f20dbc038317fdb0f0da3b512cb0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 14:03:50 +0330 Subject: [PATCH 086/775] Delete file --- render/inp.go | 37 ------------------------------------- render/tet4.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 37 deletions(-) delete mode 100644 render/inp.go diff --git a/render/inp.go b/render/inp.go deleted file mode 100644 index 69083397b..000000000 --- a/render/inp.go +++ /dev/null @@ -1,37 +0,0 @@ -package render - -import ( - "sync" -) - -//----------------------------------------------------------------------------- - -// Define the ABAQUS or CalculiX inp file requirements, if any. - -//----------------------------------------------------------------------------- - -// writeInpTet4 writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. -func writeInpTet4(wg *sync.WaitGroup, path string, layerCount int) (chan<- []*Tet4, error) { - // External code writes tetrahedra to this channel. - // This goroutine reads the channel and writes tetrahedra to the file. - c := make(chan []*Tet4) - - wg.Add(1) - go func() { - defer wg.Done() - - m := NewMeshTet4(layerCount) - defer m.WriteInp(path) - - // read finite elements from the channel and handle them - for ts := range c { - for _, t := range ts { - m.AddTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) - } - } - - m.Finalize() - }() - - return c, nil -} diff --git a/render/tet4.go b/render/tet4.go index e2e7a200e..55f99a015 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "runtime" + "sync" "time" v3 "github.com/deadsy/sdfx/vec/v3" @@ -202,3 +203,33 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { return nil } + +//----------------------------------------------------------------------------- + +// writeInpTet4 writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. +func writeInpTet4(wg *sync.WaitGroup, path string, layerCount int) (chan<- []*Tet4, error) { + // External code writes tetrahedra to this channel. + // This goroutine reads the channel and writes tetrahedra to the file. + c := make(chan []*Tet4) + + wg.Add(1) + go func() { + defer wg.Done() + + m := NewMeshTet4(layerCount) + defer m.WriteInp(path) + + // read finite elements from the channel and handle them + for ts := range c { + for _, t := range ts { + m.AddTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) + } + } + + m.Finalize() + }() + + return c, nil +} + +//----------------------------------------------------------------------------- From 4b354705860a64470a65be6f7f3da84fa0a2473d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 14:31:12 +0330 Subject: [PATCH 087/775] New design: write to tetrahedra, create mesh, ... --- examples/finite_elements/main.go | 15 +++++++++++++-- render/render.go | 29 ++++++++++++++++------------- render/tet4.go | 29 +++++++++++++++++------------ 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 91ffcca0b..e32883b5b 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -33,6 +33,17 @@ func main() { } // Render SDF3 to finite elements. - // Output file can be used by ABAQUS or CalculiX. - render.ToInpTet4(teapotSdf, "teapot.inp", render.NewMarchingTet4Uniform(200)) + r := render.NewMarchingTet4Uniform(200) + tet4s := render.ToTet4(teapotSdf, r) + + // Create a mesh out of finite elements. + _, _, layerCountZ := r.LayerCounts(teapotSdf) + m := render.NewMeshTet4(layerCountZ, tet4s) + + // Write mesh to a file. + // Written file can be used by ABAQUS or CalculiX. + err = m.WriteInp("teapot.inp") + if err != nil { + log.Fatalf("error: %s", err) + } } diff --git a/render/render.go b/render/render.go index a4b059bf4..6e7c6b73c 100644 --- a/render/render.go +++ b/render/render.go @@ -60,29 +60,32 @@ func ToTriangles( //----------------------------------------------------------------------------- -// ToInpTet4 renders an SDF3 to finite elements in the shape of tetrahedra. -// Tetrahedra would then be written to an ABAQUS or CalculiX `inp` file. -func ToInpTet4( +// ToTet4 renders an SDF3 to finite elements in the shape of 4-node tetrahedra. +func ToTet4( s sdf.SDF3, // sdf3 to render - path string, // path to filename r RenderTet4, // rendering method -) { - fmt.Printf("rendering %s (%s)\n", path, r.Info(s)) - // write the tetrahedra to an ABAQUS or CalculiX `inp` file - var wg sync.WaitGroup +) []Tet4 { + fmt.Printf("rendering %s\n", r.Info(s)) + layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) fmt.Printf("layer counts of marching are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) - output, err := writeInpTet4(&wg, path, layerCountZ) - if err != nil { - fmt.Printf("%s", err) - return - } + + // Will be filled by the rendering. + tet4s := make([]Tet4, 0) + + var wg sync.WaitGroup + + // Get the channel to be written to. + output := writeTet4(&wg, &tet4s) + // run the renderer r.Render(s, output) // stop the writer reading on the channel close(output) // wait for the file write to complete wg.Wait() + + return tet4s } //----------------------------------------------------------------------------- diff --git a/render/tet4.go b/render/tet4.go index 55f99a015..9b6d15f9d 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -39,7 +39,18 @@ type MeshTet4 struct { Lookup map[[3]float64]uint32 } -func NewMeshTet4(layerCount int) *MeshTet4 { +func NewMeshTet4(layerCount int, tet4s []Tet4) *MeshTet4 { + m := newMeshTet4(layerCount) + + // Fill out the mesh with finite elements. + for _, t := range tet4s { + m.AddTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) + } + + return m +} + +func newMeshTet4(layerCount int) *MeshTet4 { t := &MeshTet4{ T: nil, V: []v3.Vec{}, @@ -206,30 +217,24 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { //----------------------------------------------------------------------------- -// writeInpTet4 writes a stream of finite elements in the shape of tetrahedra to an ABAQUS or CalculiX `inp` file. -func writeInpTet4(wg *sync.WaitGroup, path string, layerCount int) (chan<- []*Tet4, error) { +// writeTet4 writes a stream of finite elements, in the shape of 4-node tetrahedra, to an array. +func writeTet4(wg *sync.WaitGroup, tet4s *[]Tet4) chan<- []*Tet4 { // External code writes tetrahedra to this channel. - // This goroutine reads the channel and writes tetrahedra to the file. + // This goroutine reads the channel and stores tetrahedra. c := make(chan []*Tet4) wg.Add(1) go func() { defer wg.Done() - - m := NewMeshTet4(layerCount) - defer m.WriteInp(path) - // read finite elements from the channel and handle them for ts := range c { for _, t := range ts { - m.AddTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) + *tet4s = append(*tet4s, *t) } } - - m.Finalize() }() - return c, nil + return c } //----------------------------------------------------------------------------- From 730b7579f55c3e4af138ebf57a278b6ecae7020f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 14:39:24 +0330 Subject: [PATCH 088/775] Log --- render/render.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/render.go b/render/render.go index 6e7c6b73c..af2c0b5b8 100644 --- a/render/render.go +++ b/render/render.go @@ -68,7 +68,7 @@ func ToTet4( fmt.Printf("rendering %s\n", r.Info(s)) layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) - fmt.Printf("layer counts of marching are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) + fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) // Will be filled by the rendering. tet4s := make([]Tet4, 0) From 14a00fc354fed39123d3817fcc2b8aeb66d889c6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 14:46:18 +0330 Subject: [PATCH 089/775] Clear hash table after adding tetrahedra --- render/tet4.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/render/tet4.go b/render/tet4.go index 9b6d15f9d..4a3dedeb1 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -47,6 +47,8 @@ func NewMeshTet4(layerCount int, tet4s []Tet4) *MeshTet4 { m.AddTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) } + m.finalize() + return m } @@ -100,7 +102,7 @@ func (m *MeshTet4) vertex(i int) v3.Vec { } // To be called after adding all tetrahedra to the mesh. -func (t *MeshTet4) Finalize() { +func (t *MeshTet4) finalize() { // Clear memory. t.Lookup = nil runtime.GC() From ac1996d0041f9dd5c9e44242f721c5d8083f9696 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 14:48:44 +0330 Subject: [PATCH 090/775] Make some funcs private, do not expose --- render/tet4.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 4a3dedeb1..0e8232e28 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -44,7 +44,7 @@ func NewMeshTet4(layerCount int, tet4s []Tet4) *MeshTet4 { // Fill out the mesh with finite elements. for _, t := range tet4s { - m.AddTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) + m.addTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) } m.finalize() @@ -71,7 +71,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { // Layer number and 4 nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) AddTet4(l int, a, b, c, d v3.Vec) { +func (m *MeshTet4) addTet4(l int, a, b, c, d v3.Vec) { m.T[l] = append(m.T[l], m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) } @@ -109,17 +109,17 @@ func (t *MeshTet4) finalize() { } // Number of layers along the Z axis. -func (m *MeshTet4) LayerCount() int { +func (m *MeshTet4) layerCount() int { return len(m.T) } // Number of tetrahedra on a layer. -func (m *MeshTet4) Tet4CountOnLayer(l int) int { +func (m *MeshTet4) tet4CountOnLayer(l int) int { return len(m.T[l]) / 4 } // Number of tetrahedra for all layers. -func (m *MeshTet4) Tet4Count() int { +func (m *MeshTet4) tet4Count() int { var count int for _, t := range m.T { count += len(t) / 4 @@ -131,7 +131,7 @@ func (m *MeshTet4) Tet4Count() int { // Tetrahedron index on layer is input. // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) Tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { +func (m *MeshTet4) tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { return m.T[l][i*4], m.T[l][i*4+1], m.T[l][i*4+2], m.T[l][i*4+3] } @@ -139,20 +139,20 @@ func (m *MeshTet4) Tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { // Tetrahedron index on layer is input. // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) Tet4Vertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { +func (m *MeshTet4) tet4Vertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { return m.V[m.T[l][i*4]], m.V[m.T[l][i*4+1]], m.V[m.T[l][i*4+2]], m.V[m.T[l][i*4+3]] } // Write mesh to ABAQUS or CalculiX `inp` file. func (m *MeshTet4) WriteInp(path string) error { - return m.WriteInpLayers(path, 0, m.LayerCount()) + return m.WriteInpLayers(path, 0, m.layerCount()) } // Write specific layers of mesh to ABAQUS or CalculiX `inp` file. // Result would include start layer. // Result would exclude end layer. func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { - if 0 <= layerStart && layerStart < layerEnd && layerEnd <= m.LayerCount() { + if 0 <= layerStart && layerStart < layerEnd && layerEnd <= m.layerCount() { // Good. } else { return fmt.Errorf("start or end layer is beyond range") @@ -203,8 +203,8 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { var eleID uint32 var nodeID0, nodeID1, nodeID2, nodeID3 uint32 for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.Tet4CountOnLayer(l); i++ { - nodeID0, nodeID1, nodeID2, nodeID3 = m.Tet4Indicies(l, i) + for i := 0; i < m.tet4CountOnLayer(l); i++ { + nodeID0, nodeID1, nodeID2, nodeID3 = m.tet4Indicies(l, i) // ID starts from one not zero. _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, nodeID0+1, nodeID1+1, nodeID2+1, nodeID3+1)) if err != nil { From 00009e4a3cbbabcaf2e3703d893b92878e6e942d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 14:57:08 +0330 Subject: [PATCH 091/775] Write just some layers of mesh to `inp` file --- examples/finite_elements/main.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index e32883b5b..ecc4f7fa0 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -46,4 +46,10 @@ func main() { if err != nil { log.Fatalf("error: %s", err) } + + // Write just some layers of mesh to a file. + err = m.WriteInpLayers("teapot-some-layers.inp", 10, 21) + if err != nil { + log.Fatalf("error: %s", err) + } } From 830cb07f196319495ceabd780be383186d86caea Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 15:25:05 +0330 Subject: [PATCH 092/775] Fix typo --- render/marchtet4.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index ea2402c70..110f2ee8e 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -63,7 +63,7 @@ type MarchingTet4Uniform struct { meshCells int // number of cells on the longest axis of bounding box. e.g 200 } -// NewMarchingTet4Uniform returns a RenderFE object. +// NewMarchingTet4Uniform returns a RenderTet4 object. func NewMarchingTet4Uniform(meshCells int) *MarchingTet4Uniform { return &MarchingTet4Uniform{ meshCells: meshCells, From 847d8915176d150f40aec30adce51f4d868def3c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 15:40:34 +0330 Subject: [PATCH 093/775] Simpler API --- examples/finite_elements/main.go | 6 +----- render/tet4.go | 9 +++++++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index ecc4f7fa0..08d1bb720 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -33,12 +33,8 @@ func main() { } // Render SDF3 to finite elements. - r := render.NewMarchingTet4Uniform(200) - tet4s := render.ToTet4(teapotSdf, r) - // Create a mesh out of finite elements. - _, _, layerCountZ := r.LayerCounts(teapotSdf) - m := render.NewMeshTet4(layerCountZ, tet4s) + m := render.NewMeshTet4(teapotSdf, render.NewMarchingTet4Uniform(200)) // Write mesh to a file. // Written file can be used by ABAQUS or CalculiX. diff --git a/render/tet4.go b/render/tet4.go index 0e8232e28..36a88bc77 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "github.com/deadsy/sdfx/sdf" v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -39,8 +40,12 @@ type MeshTet4 struct { Lookup map[[3]float64]uint32 } -func NewMeshTet4(layerCount int, tet4s []Tet4) *MeshTet4 { - m := newMeshTet4(layerCount) +func NewMeshTet4(s sdf.SDF3, r RenderTet4) *MeshTet4 { + tet4s := ToTet4(s, r) + + _, _, layerCountZ := r.LayerCounts(s) + + m := newMeshTet4(layerCountZ) // Fill out the mesh with finite elements. for _, t := range tet4s { From 49227210cd5064b8491ef4d728f4df6994141bbe Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 15:44:26 +0330 Subject: [PATCH 094/775] Change API --- examples/finite_elements/main.go | 2 +- render/tet4.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 08d1bb720..c51757d18 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -34,7 +34,7 @@ func main() { // Render SDF3 to finite elements. // Create a mesh out of finite elements. - m := render.NewMeshTet4(teapotSdf, render.NewMarchingTet4Uniform(200)) + m, _ := render.NewMeshTet4(teapotSdf, render.NewMarchingTet4Uniform(200)) // Write mesh to a file. // Written file can be used by ABAQUS or CalculiX. diff --git a/render/tet4.go b/render/tet4.go index 36a88bc77..b1739504f 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -40,7 +40,8 @@ type MeshTet4 struct { Lookup map[[3]float64]uint32 } -func NewMeshTet4(s sdf.SDF3, r RenderTet4) *MeshTet4 { +// To get a new mesh and number of its layers along Z-axis. +func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { tet4s := ToTet4(s, r) _, _, layerCountZ := r.LayerCounts(s) @@ -54,7 +55,7 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) *MeshTet4 { m.finalize() - return m + return m, layerCountZ } func newMeshTet4(layerCount int) *MeshTet4 { From 7d04d2f9a58a903eb2bb52ff3364035e4b188f4a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 26 Feb 2023 16:04:37 +0330 Subject: [PATCH 095/775] Change example: more clear --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c51757d18..393928665 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -44,7 +44,7 @@ func main() { } // Write just some layers of mesh to a file. - err = m.WriteInpLayers("teapot-some-layers.inp", 10, 21) + err = m.WriteInpLayers("teapot-some-layers.inp", 0, 10) if err != nil { log.Fatalf("error: %s", err) } From af1ccf356d6c43a6866c3c5f37f3a1410aadc9e0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 27 Feb 2023 13:42:05 +0330 Subject: [PATCH 096/775] Bring over marching cubes: triangle vs tet4... --- render/marchtet4.go | 126 +++++++++++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 36 deletions(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index 110f2ee8e..f24cb0956 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -13,51 +13,105 @@ import ( func marchingTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { var tetrahedra []*Tet4 - size := box.Size() + base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) - - _, _, nz := steps.X, steps.Y, steps.Z - - for z := 0; z < nz; z++ { - - h := float64(z) - - // Constant hard-coded tetrahedra vertices to develop and debug the output API. - // https://cs.stackexchange.com/a/90011/67985 - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 0, Y: 0, Z: h + 1}, {X: 0, Y: 1, Z: h + 1}, {X: 1, Y: 1, Z: h + 1}}, - layer: z, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 0, Y: 1, Z: h}, {X: 0, Y: 1, Z: h + 1}, {X: 1, Y: 1, Z: h + 1}}, - layer: z, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 0, Y: 0, Z: h + 1}, {X: 1, Y: 0, Z: h + 1}, {X: 1, Y: 1, Z: h + 1}}, - layer: z, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 1, Y: 0, Z: h}, {X: 1, Y: 0, Z: h + 1}, {X: 1, Y: 1, Z: h + 1}}, - layer: z, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 0, Y: 1, Z: h}, {X: 1, Y: 1, Z: h}, {X: 1, Y: 1, Z: h + 1}}, - layer: z, - }) - tetrahedra = append(tetrahedra, &Tet4{ - V: [4]v3.Vec{{X: 0, Y: 0, Z: h}, {X: 1, Y: 0, Z: h}, {X: 1, Y: 1, Z: h}, {X: 1, Y: 1, Z: h + 1}}, - layer: z, - }) + inc := size.Div(conv.V3iToV3(steps)) + + // start the evaluation routines + evalRoutines() + + // create the SDF layer cache + l := newLayerYZ(base, inc, steps) + // evaluate the SDF for x = 0 + l.Evaluate(s, 0) + + nx, ny, nz := steps.X, steps.Y, steps.Z + dx, dy, dz := inc.X, inc.Y, inc.Z + + var p v3.Vec + p.X = base.X + for x := 0; x < nx; x++ { + // read the x + 1 layer + l.Evaluate(s, x+1) + // process all cubes in the x and x + 1 layers + p.Y = base.Y + for y := 0; y < ny; y++ { + p.Z = base.Z + for z := 0; z < nz; z++ { + x0, y0, z0 := p.X, p.Y, p.Z + x1, y1, z1 := x0+dx, y0+dy, z0+dz + corners := [8]v3.Vec{ + {x0, y0, z0}, + {x1, y0, z0}, + {x1, y1, z0}, + {x0, y1, z0}, + {x0, y0, z1}, + {x1, y0, z1}, + {x1, y1, z1}, + {x0, y1, z1}} + values := [8]float64{ + l.Get(0, y, z), + l.Get(1, y, z), + l.Get(1, y+1, z), + l.Get(0, y+1, z), + l.Get(0, y, z+1), + l.Get(1, y, z+1), + l.Get(1, y+1, z+1), + l.Get(0, y+1, z+1)} + tetrahedra = append(tetrahedra, mcToTet4(corners, values, 0)...) + p.Z += dz + } + p.Y += dy + } + p.X += dx } - // TODO: Logic. - return tetrahedra } //----------------------------------------------------------------------------- +func mcToTet4(p [8]v3.Vec, v [8]float64, x float64) []*Tet4 { + // which of the 0..255 patterns do we have? + index := 0 + for i := 0; i < 8; i++ { + if v[i] < x { + index |= 1 << uint(i) + } + } + // do we have any triangles to create? + if mcEdgeTable[index] == 0 { + return nil + } + // work out the interpolated points on the edges + var points [12]v3.Vec + for i := 0; i < 12; i++ { + bit := 1 << uint(i) + if mcEdgeTable[index]&bit != 0 { + a := mcPairTable[i][0] + b := mcPairTable[i][1] + points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) + } + } + // create the triangles + table := mcTriangleTable[index] + count := len(table) / 3 + result := make([]*Triangle3, 0, count) + for i := 0; i < count; i++ { + t := Triangle3{} + t.V[2] = points[table[i*3+0]] + t.V[1] = points[table[i*3+1]] + t.V[0] = points[table[i*3+2]] + if !t.Degenerate(0) { + result = append(result, &t) + } + } + return result +} + +//----------------------------------------------------------------------------- + // MarchingTet4Uniform renders using marching Tetrahedra with uniform space sampling. type MarchingTet4Uniform struct { meshCells int // number of cells on the longest axis of bounding box. e.g 200 From ec45e5b0ba0552306f1d1e0b0d8aa59482de3507 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 27 Feb 2023 13:50:27 +0330 Subject: [PATCH 097/775] Rename --- render/marchtet4.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index f24cb0956..bd8e9567b 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -10,7 +10,7 @@ import ( //----------------------------------------------------------------------------- -func marchingTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { +func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { var tetrahedra []*Tet4 size := box.Size() @@ -160,7 +160,7 @@ func (r *MarchingTet4Uniform) Render(s sdf.SDF3, output chan<- []*Tet4) { bb1Size = bb1Size.Ceil().AddScalar(1) bb1Size = bb1Size.MulScalar(meshInc) bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingTet4(s, bb, meshInc) + output <- marchingCubesTet4(s, bb, meshInc) } //----------------------------------------------------------------------------- From 98bb6681ea030d0900d3d2cbd6916bbcb3077c88 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 27 Feb 2023 13:56:05 +0330 Subject: [PATCH 098/775] Initial version: creation of tet4 --- render/marchtet4.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index bd8e9567b..c1ea73aa9 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -59,7 +59,7 @@ func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { l.Get(1, y, z+1), l.Get(1, y+1, z+1), l.Get(0, y+1, z+1)} - tetrahedra = append(tetrahedra, mcToTet4(corners, values, 0)...) + tetrahedra = append(tetrahedra, mcToTet4(corners, values, 0, z)...) p.Z += dz } p.Y += dy @@ -72,7 +72,7 @@ func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { //----------------------------------------------------------------------------- -func mcToTet4(p [8]v3.Vec, v [8]float64, x float64) []*Tet4 { +func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // which of the 0..255 patterns do we have? index := 0 for i := 0; i < 8; i++ { @@ -97,15 +97,16 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64) []*Tet4 { // create the triangles table := mcTriangleTable[index] count := len(table) / 3 - result := make([]*Triangle3, 0, count) + result := make([]*Tet4, 0, count) for i := 0; i < count; i++ { - t := Triangle3{} + t := Tet4{ + V: [4]v3.Vec{}, + layer: layerZ, + } t.V[2] = points[table[i*3+0]] t.V[1] = points[table[i*3+1]] t.V[0] = points[table[i*3+2]] - if !t.Degenerate(0) { - result = append(result, &t) - } + result = append(result, &t) } return result } From 612a80401c78cd14b0488cccab5490a25ed71553 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 27 Feb 2023 14:11:36 +0330 Subject: [PATCH 099/775] Write first 32 layers to `inp` file --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 393928665..6eff5eb41 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -44,7 +44,7 @@ func main() { } // Write just some layers of mesh to a file. - err = m.WriteInpLayers("teapot-some-layers.inp", 0, 10) + err = m.WriteInpLayers("teapot-some-layers.inp", 0, 32) if err != nil { log.Fatalf("error: %s", err) } From f2c9cad2c1dbd4b3b6cec8369edaaed8f8a1fbf5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 28 Feb 2023 13:46:52 +0330 Subject: [PATCH 100/775] To improve performance & handle float point error: Modify `addVertex` strategy --- render/tet4.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index b1739504f..98b651f57 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -37,7 +37,7 @@ type MeshTet4 struct { // All coordinates are unique. V []v3.Vec // Used to avoid repeating vertices when adding a new tetrahedron. - Lookup map[[3]float64]uint32 + Lookup map[[3]int32]uint32 } // To get a new mesh and number of its layers along Z-axis. @@ -62,7 +62,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { t := &MeshTet4{ T: nil, V: []v3.Vec{}, - Lookup: map[[3]float64]uint32{}, + Lookup: map[[3]int32]uint32{}, } // Initialize. @@ -82,9 +82,10 @@ func (m *MeshTet4) addTet4(l int, a, b, c, d v3.Vec) { } func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { - // TODO: Binary insertion sort and search to eliminate extra allocation - // TODO: Consider epsilon in comparison and use int (*100) for searching - if vertID, ok := m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}]; ok { + // Deduplicate by removing small details and use of epsilon + epsilon := float64(0.0001) + key := [3]int32{int32((vert.X + epsilon) * 1000), int32((vert.Y + epsilon) * 1000), int32((vert.Z + epsilon) * 1000)} + if vertID, ok := m.Lookup[key]; ok { // Vertex already exists. It's repeated. return vertID } @@ -93,7 +94,7 @@ func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { m.V = append(m.V, vert) // Store index of the appended vertex. - m.Lookup[[3]float64{vert.X, vert.Y, vert.Z}] = uint32(m.vertexCount() - 1) + m.Lookup[key] = uint32(m.vertexCount() - 1) // Return index of the appended vertex. return uint32(m.vertexCount() - 1) From a44b2699cfb32f3ae5a47f6ef764d4b252861c5c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 28 Feb 2023 15:29:34 +0330 Subject: [PATCH 101/775] New type: simpler? --- render/lookup.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ render/tet4.go | 34 +++++++----------------------- 2 files changed, 61 insertions(+), 27 deletions(-) create mode 100644 render/lookup.go diff --git a/render/lookup.go b/render/lookup.go new file mode 100644 index 000000000..98c789359 --- /dev/null +++ b/render/lookup.go @@ -0,0 +1,54 @@ +package render + +import ( + "runtime" + + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// To avoid repeating vertices on vertex buffer. +type Lookup struct { + hashTable map[[3]int32]uint32 // + V *[]v3.Vec // Pointer: to be able to append to it. +} + +func NewLookup(V *[]v3.Vec) *Lookup { + l := Lookup{ + hashTable: map[[3]int32]uint32{}, + V: V, + } + l.hashTable = make(map[[3]int32]uint32, 0) + return &l +} + +// Add vertex to buffer and get vertex ID. +// All vertices would be unique. Not repeated. +func (l Lookup) Id(v v3.Vec) uint32 { + // Deduplicate by removing small details and use of epsilon + epsilon := float64(0.0001) + key := [3]int32{int32((v.X + epsilon) * 1000), int32((v.Y + epsilon) * 1000), int32((v.Z + epsilon) * 1000)} + if vID, ok := l.hashTable[key]; ok { + // Vertex already exists. It's repeated. + return vID + } + + // Vertex is new, so append it. + *l.V = append(*l.V, v) + + // Store index of the appended vertex. + l.hashTable[key] = uint32(l.vertexCount() - 1) + + // Return index of the appended vertex. + return uint32(l.vertexCount() - 1) +} + +func (l *Lookup) vertexCount() int { + return len(*l.V) +} + +// To be called after adding all vertices to the vertex buffer. +func (l *Lookup) Destroy() { + // Clear memory. + l.hashTable = nil + runtime.GC() +} diff --git a/render/tet4.go b/render/tet4.go index 98b651f57..0a9f52e89 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -3,7 +3,6 @@ package render import ( "fmt" "os" - "runtime" "sync" "time" @@ -37,7 +36,7 @@ type MeshTet4 struct { // All coordinates are unique. V []v3.Vec // Used to avoid repeating vertices when adding a new tetrahedron. - Lookup map[[3]int32]uint32 + Lookup *Lookup } // To get a new mesh and number of its layers along Z-axis. @@ -53,7 +52,7 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { m.addTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) } - m.finalize() + m.Lookup.Destroy() return m, layerCountZ } @@ -62,7 +61,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { t := &MeshTet4{ T: nil, V: []v3.Vec{}, - Lookup: map[[3]int32]uint32{}, + Lookup: nil, } // Initialize. @@ -71,6 +70,9 @@ func newMeshTet4(layerCount int) *MeshTet4 { t.T[l] = make([]uint32, 0) } + // Initialize + t.Lookup = NewLookup(&t.V) + return t } @@ -82,22 +84,7 @@ func (m *MeshTet4) addTet4(l int, a, b, c, d v3.Vec) { } func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { - // Deduplicate by removing small details and use of epsilon - epsilon := float64(0.0001) - key := [3]int32{int32((vert.X + epsilon) * 1000), int32((vert.Y + epsilon) * 1000), int32((vert.Z + epsilon) * 1000)} - if vertID, ok := m.Lookup[key]; ok { - // Vertex already exists. It's repeated. - return vertID - } - - // Vertex is new, so append it. - m.V = append(m.V, vert) - - // Store index of the appended vertex. - m.Lookup[key] = uint32(m.vertexCount() - 1) - - // Return index of the appended vertex. - return uint32(m.vertexCount() - 1) + return m.Lookup.Id(vert) } func (m *MeshTet4) vertexCount() int { @@ -108,13 +95,6 @@ func (m *MeshTet4) vertex(i int) v3.Vec { return m.V[i] } -// To be called after adding all tetrahedra to the mesh. -func (t *MeshTet4) finalize() { - // Clear memory. - t.Lookup = nil - runtime.GC() -} - // Number of layers along the Z axis. func (m *MeshTet4) layerCount() int { return len(m.T) From 2bbe2599401b0b992676da2618a2ff87e63da34d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 28 Feb 2023 15:30:40 +0330 Subject: [PATCH 102/775] Rename file --- render/{lookup.go => vertexbuffer.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename render/{lookup.go => vertexbuffer.go} (100%) diff --git a/render/lookup.go b/render/vertexbuffer.go similarity index 100% rename from render/lookup.go rename to render/vertexbuffer.go From 6aa9e8af223973fb6054cae33caf173a7185bed6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 10:36:16 +0330 Subject: [PATCH 103/775] Rename type --- render/tet4.go | 4 ++-- render/vertexbuffer.go | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 0a9f52e89..e44a1718f 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -36,7 +36,7 @@ type MeshTet4 struct { // All coordinates are unique. V []v3.Vec // Used to avoid repeating vertices when adding a new tetrahedron. - Lookup *Lookup + Lookup *VertexBuffer } // To get a new mesh and number of its layers along Z-axis. @@ -71,7 +71,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { } // Initialize - t.Lookup = NewLookup(&t.V) + t.Lookup = NewVertexBuffer(&t.V) return t } diff --git a/render/vertexbuffer.go b/render/vertexbuffer.go index 98c789359..4666e6926 100644 --- a/render/vertexbuffer.go +++ b/render/vertexbuffer.go @@ -7,48 +7,48 @@ import ( ) // To avoid repeating vertices on vertex buffer. -type Lookup struct { +type VertexBuffer struct { hashTable map[[3]int32]uint32 // V *[]v3.Vec // Pointer: to be able to append to it. } -func NewLookup(V *[]v3.Vec) *Lookup { - l := Lookup{ +func NewVertexBuffer(V *[]v3.Vec) *VertexBuffer { + b := VertexBuffer{ hashTable: map[[3]int32]uint32{}, V: V, } - l.hashTable = make(map[[3]int32]uint32, 0) - return &l + b.hashTable = make(map[[3]int32]uint32, 0) + return &b } // Add vertex to buffer and get vertex ID. // All vertices would be unique. Not repeated. -func (l Lookup) Id(v v3.Vec) uint32 { +func (b VertexBuffer) Id(v v3.Vec) uint32 { // Deduplicate by removing small details and use of epsilon epsilon := float64(0.0001) key := [3]int32{int32((v.X + epsilon) * 1000), int32((v.Y + epsilon) * 1000), int32((v.Z + epsilon) * 1000)} - if vID, ok := l.hashTable[key]; ok { + if vID, ok := b.hashTable[key]; ok { // Vertex already exists. It's repeated. return vID } // Vertex is new, so append it. - *l.V = append(*l.V, v) + *b.V = append(*b.V, v) // Store index of the appended vertex. - l.hashTable[key] = uint32(l.vertexCount() - 1) + b.hashTable[key] = uint32(b.vertexCount() - 1) // Return index of the appended vertex. - return uint32(l.vertexCount() - 1) + return uint32(b.vertexCount() - 1) } -func (l *Lookup) vertexCount() int { - return len(*l.V) +func (b *VertexBuffer) vertexCount() int { + return len(*b.V) } // To be called after adding all vertices to the vertex buffer. -func (l *Lookup) Destroy() { +func (b *VertexBuffer) Destroy() { // Clear memory. - l.hashTable = nil + b.hashTable = nil runtime.GC() } From 58709189df43ae375763593a0cb252f8037499ce Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 10:41:14 +0330 Subject: [PATCH 104/775] Rename field --- render/tet4.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index e44a1718f..6dd880caa 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -36,7 +36,7 @@ type MeshTet4 struct { // All coordinates are unique. V []v3.Vec // Used to avoid repeating vertices when adding a new tetrahedron. - Lookup *VertexBuffer + VBuff *VertexBuffer } // To get a new mesh and number of its layers along Z-axis. @@ -52,16 +52,16 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { m.addTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) } - m.Lookup.Destroy() + m.VBuff.Destroy() return m, layerCountZ } func newMeshTet4(layerCount int) *MeshTet4 { t := &MeshTet4{ - T: nil, - V: []v3.Vec{}, - Lookup: nil, + T: nil, + V: []v3.Vec{}, + VBuff: nil, } // Initialize. @@ -71,7 +71,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { } // Initialize - t.Lookup = NewVertexBuffer(&t.V) + t.VBuff = NewVertexBuffer(&t.V) return t } @@ -84,7 +84,7 @@ func (m *MeshTet4) addTet4(l int, a, b, c, d v3.Vec) { } func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { - return m.Lookup.Id(vert) + return m.VBuff.Id(vert) } func (m *MeshTet4) vertexCount() int { From 1b2b07277cc2c694622f8623dd4637e8ccc4bacd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 11:13:59 +0330 Subject: [PATCH 105/775] Write only required nodes, those of elements --- render/tet4.go | 49 +++++++++++++++++++++++++++++++++--------- render/vertexbuffer.go | 1 + 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 6dd880caa..a824d4854 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -170,13 +170,39 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { return err } - var node v3.Vec - for i := 0; i < m.vertexCount(); i++ { - node = m.vertex(i) - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", i+1, float32(node.X), float32(node.Y), float32(node.Z))) - if err != nil { - return err + // To write only required nodes to the file. + vs := []v3.Vec{} + vsBuff := NewVertexBuffer(&vs) + + var node0, node1, node2, node3 v3.Vec + var id0, id1, id2, id3 uint32 + for l := layerStart; l < layerEnd; l++ { + for i := 0; i < m.tet4CountOnLayer(l); i++ { + node0, node1, node2, node3 = m.tet4Vertices(l, i) + id0 = vsBuff.Id(node0) + id1 = vsBuff.Id(node1) + id2 = vsBuff.Id(node2) + id3 = vsBuff.Id(node3) + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id0+1, float32(node0.X), float32(node0.Y), float32(node0.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id1+1, float32(node1.X), float32(node1.Y), float32(node1.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id2+1, float32(node2.X), float32(node2.Y), float32(node2.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id3+1, float32(node3.X), float32(node3.Y), float32(node3.Z))) + if err != nil { + return err + } } } @@ -188,12 +214,15 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { } var eleID uint32 - var nodeID0, nodeID1, nodeID2, nodeID3 uint32 for l := layerStart; l < layerEnd; l++ { for i := 0; i < m.tet4CountOnLayer(l); i++ { - nodeID0, nodeID1, nodeID2, nodeID3 = m.tet4Indicies(l, i) + node0, node1, node2, node3 = m.tet4Vertices(l, i) + id0 = vsBuff.Id(node0) + id1 = vsBuff.Id(node1) + id2 = vsBuff.Id(node2) + id3 = vsBuff.Id(node3) // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, nodeID0+1, nodeID1+1, nodeID2+1, nodeID3+1)) + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, id0+1, id1+1, id2+1, id3+1)) if err != nil { return err } diff --git a/render/vertexbuffer.go b/render/vertexbuffer.go index 4666e6926..428846410 100644 --- a/render/vertexbuffer.go +++ b/render/vertexbuffer.go @@ -22,6 +22,7 @@ func NewVertexBuffer(V *[]v3.Vec) *VertexBuffer { } // Add vertex to buffer and get vertex ID. +// If vertex is already available on the buffer, its ID is just returned. // All vertices would be unique. Not repeated. func (b VertexBuffer) Id(v v3.Vec) uint32 { // Deduplicate by removing small details and use of epsilon From 148968a38bba3c578bc70eeff01315151aa1215f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 11:19:56 +0330 Subject: [PATCH 106/775] Clear hash table of vertex buffer --- render/tet4.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/tet4.go b/render/tet4.go index a824d4854..7ceabbd00 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -173,6 +173,7 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { // To write only required nodes to the file. vs := []v3.Vec{} vsBuff := NewVertexBuffer(&vs) + defer vsBuff.Destroy() // Clean up vertex buffer memory. var node0, node1, node2, node3 v3.Vec var id0, id1, id2, id3 uint32 From e7ffbf95a3ed8d75093c2e576397a7f794fbd148 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 11:21:46 +0330 Subject: [PATCH 107/775] Rename func --- render/tet4.go | 4 ++-- render/vertexbuffer.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 7ceabbd00..848333428 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -52,7 +52,7 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { m.addTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) } - m.VBuff.Destroy() + m.VBuff.DestroyHashTable() return m, layerCountZ } @@ -173,7 +173,7 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { // To write only required nodes to the file. vs := []v3.Vec{} vsBuff := NewVertexBuffer(&vs) - defer vsBuff.Destroy() // Clean up vertex buffer memory. + defer vsBuff.DestroyHashTable() var node0, node1, node2, node3 v3.Vec var id0, id1, id2, id3 uint32 diff --git a/render/vertexbuffer.go b/render/vertexbuffer.go index 428846410..2edb16bae 100644 --- a/render/vertexbuffer.go +++ b/render/vertexbuffer.go @@ -48,7 +48,7 @@ func (b *VertexBuffer) vertexCount() int { } // To be called after adding all vertices to the vertex buffer. -func (b *VertexBuffer) Destroy() { +func (b *VertexBuffer) DestroyHashTable() { // Clear memory. b.hashTable = nil runtime.GC() From d67bdca6dff5cb830f874e579c2cdbf57a31749c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 12:08:50 +0330 Subject: [PATCH 108/775] Move coordinates to vertex buffer --- render/tet4.go | 21 +++++++++------------ render/vertexbuffer.go | 29 ++++++++++++++++++----------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 848333428..efc3cd206 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -34,7 +34,6 @@ type MeshTet4 struct { T [][]uint32 // Vertex buffer. // All coordinates are unique. - V []v3.Vec // Used to avoid repeating vertices when adding a new tetrahedron. VBuff *VertexBuffer } @@ -52,7 +51,7 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { m.addTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) } - m.VBuff.DestroyHashTable() + defer m.VBuff.DestroyHashTable() return m, layerCountZ } @@ -60,7 +59,6 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { func newMeshTet4(layerCount int) *MeshTet4 { t := &MeshTet4{ T: nil, - V: []v3.Vec{}, VBuff: nil, } @@ -71,7 +69,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { } // Initialize - t.VBuff = NewVertexBuffer(&t.V) + t.VBuff = NewVertexBuffer() return t } @@ -88,11 +86,11 @@ func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { } func (m *MeshTet4) vertexCount() int { - return len(m.V) + return m.VBuff.VertexCount() } -func (m *MeshTet4) vertex(i int) v3.Vec { - return m.V[i] +func (m *MeshTet4) vertex(i uint32) v3.Vec { + return m.VBuff.Vertex(i) } // Number of layers along the Z axis. @@ -108,8 +106,8 @@ func (m *MeshTet4) tet4CountOnLayer(l int) int { // Number of tetrahedra for all layers. func (m *MeshTet4) tet4Count() int { var count int - for _, t := range m.T { - count += len(t) / 4 + for _, l := range m.T { + count += len(l) / 4 } return count } @@ -127,7 +125,7 @@ func (m *MeshTet4) tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. func (m *MeshTet4) tet4Vertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { - return m.V[m.T[l][i*4]], m.V[m.T[l][i*4+1]], m.V[m.T[l][i*4+2]], m.V[m.T[l][i*4+3]] + return m.VBuff.Vertex(m.T[l][i*4]), m.VBuff.Vertex(m.T[l][i*4+1]), m.VBuff.Vertex(m.T[l][i*4+2]), m.VBuff.Vertex(m.T[l][i*4+3]) } // Write mesh to ABAQUS or CalculiX `inp` file. @@ -171,8 +169,7 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { } // To write only required nodes to the file. - vs := []v3.Vec{} - vsBuff := NewVertexBuffer(&vs) + vsBuff := NewVertexBuffer() defer vsBuff.DestroyHashTable() var node0, node1, node2, node3 v3.Vec diff --git a/render/vertexbuffer.go b/render/vertexbuffer.go index 2edb16bae..1a93c3be4 100644 --- a/render/vertexbuffer.go +++ b/render/vertexbuffer.go @@ -8,23 +8,25 @@ import ( // To avoid repeating vertices on vertex buffer. type VertexBuffer struct { - hashTable map[[3]int32]uint32 // - V *[]v3.Vec // Pointer: to be able to append to it. + // To store index of vertices. Repeated vertices would have the same index. + hashTable map[[3]int32]uint32 + // To store coordinates of vertices. + V []v3.Vec } -func NewVertexBuffer(V *[]v3.Vec) *VertexBuffer { +func NewVertexBuffer() *VertexBuffer { b := VertexBuffer{ hashTable: map[[3]int32]uint32{}, - V: V, + V: []v3.Vec{}, } - b.hashTable = make(map[[3]int32]uint32, 0) + return &b } // Add vertex to buffer and get vertex ID. // If vertex is already available on the buffer, its ID is just returned. // All vertices would be unique. Not repeated. -func (b VertexBuffer) Id(v v3.Vec) uint32 { +func (b *VertexBuffer) Id(v v3.Vec) uint32 { // Deduplicate by removing small details and use of epsilon epsilon := float64(0.0001) key := [3]int32{int32((v.X + epsilon) * 1000), int32((v.Y + epsilon) * 1000), int32((v.Z + epsilon) * 1000)} @@ -34,22 +36,27 @@ func (b VertexBuffer) Id(v v3.Vec) uint32 { } // Vertex is new, so append it. - *b.V = append(*b.V, v) + b.V = append(b.V, v) // Store index of the appended vertex. - b.hashTable[key] = uint32(b.vertexCount() - 1) + b.hashTable[key] = uint32(b.VertexCount() - 1) // Return index of the appended vertex. - return uint32(b.vertexCount() - 1) + return uint32(b.VertexCount() - 1) } -func (b *VertexBuffer) vertexCount() int { - return len(*b.V) +func (b *VertexBuffer) VertexCount() int { + return len(b.V) } // To be called after adding all vertices to the vertex buffer. +// Call if you are sure that no new vertex will be added to the vertex buffer. func (b *VertexBuffer) DestroyHashTable() { // Clear memory. b.hashTable = nil runtime.GC() } + +func (b *VertexBuffer) Vertex(i uint32) v3.Vec { + return b.V[i] +} From c17363db5da5ca8283c30f05d5563aa50ddce7e7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 12:31:04 +0330 Subject: [PATCH 109/775] New buffer pkg --- render/buffer/buffer.go | 2 ++ render/{vertexbuffer.go => buffer/tet4vertex.go} | 2 +- render/tet4.go | 7 ++++--- 3 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 render/buffer/buffer.go rename render/{vertexbuffer.go => buffer/tet4vertex.go} (99%) diff --git a/render/buffer/buffer.go b/render/buffer/buffer.go new file mode 100644 index 000000000..30b3e0994 --- /dev/null +++ b/render/buffer/buffer.go @@ -0,0 +1,2 @@ +// Index and vertex buffers +package buffer diff --git a/render/vertexbuffer.go b/render/buffer/tet4vertex.go similarity index 99% rename from render/vertexbuffer.go rename to render/buffer/tet4vertex.go index 1a93c3be4..7a34dbc8c 100644 --- a/render/vertexbuffer.go +++ b/render/buffer/tet4vertex.go @@ -1,4 +1,4 @@ -package render +package buffer import ( "runtime" diff --git a/render/tet4.go b/render/tet4.go index efc3cd206..4072831b8 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -6,6 +6,7 @@ import ( "sync" "time" + "github.com/deadsy/sdfx/render/buffer" "github.com/deadsy/sdfx/sdf" v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -35,7 +36,7 @@ type MeshTet4 struct { // Vertex buffer. // All coordinates are unique. // Used to avoid repeating vertices when adding a new tetrahedron. - VBuff *VertexBuffer + VBuff *buffer.VertexBuffer } // To get a new mesh and number of its layers along Z-axis. @@ -69,7 +70,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { } // Initialize - t.VBuff = NewVertexBuffer() + t.VBuff = buffer.NewVertexBuffer() return t } @@ -169,7 +170,7 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { } // To write only required nodes to the file. - vsBuff := NewVertexBuffer() + vsBuff := buffer.NewVertexBuffer() defer vsBuff.DestroyHashTable() var node0, node1, node2, node3 v3.Vec From 3fa76f100224fba2abb6949169e8d73ad0191a5d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 12:33:04 +0330 Subject: [PATCH 110/775] Rename --- render/buffer/tet4vertex.go | 14 +++++++------- render/tet4.go | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/render/buffer/tet4vertex.go b/render/buffer/tet4vertex.go index 7a34dbc8c..1a7e9d6f7 100644 --- a/render/buffer/tet4vertex.go +++ b/render/buffer/tet4vertex.go @@ -7,15 +7,15 @@ import ( ) // To avoid repeating vertices on vertex buffer. -type VertexBuffer struct { +type Tet4VertexBuffer struct { // To store index of vertices. Repeated vertices would have the same index. hashTable map[[3]int32]uint32 // To store coordinates of vertices. V []v3.Vec } -func NewVertexBuffer() *VertexBuffer { - b := VertexBuffer{ +func NewTet4VertexBuffer() *Tet4VertexBuffer { + b := Tet4VertexBuffer{ hashTable: map[[3]int32]uint32{}, V: []v3.Vec{}, } @@ -26,7 +26,7 @@ func NewVertexBuffer() *VertexBuffer { // Add vertex to buffer and get vertex ID. // If vertex is already available on the buffer, its ID is just returned. // All vertices would be unique. Not repeated. -func (b *VertexBuffer) Id(v v3.Vec) uint32 { +func (b *Tet4VertexBuffer) Id(v v3.Vec) uint32 { // Deduplicate by removing small details and use of epsilon epsilon := float64(0.0001) key := [3]int32{int32((v.X + epsilon) * 1000), int32((v.Y + epsilon) * 1000), int32((v.Z + epsilon) * 1000)} @@ -45,18 +45,18 @@ func (b *VertexBuffer) Id(v v3.Vec) uint32 { return uint32(b.VertexCount() - 1) } -func (b *VertexBuffer) VertexCount() int { +func (b *Tet4VertexBuffer) VertexCount() int { return len(b.V) } // To be called after adding all vertices to the vertex buffer. // Call if you are sure that no new vertex will be added to the vertex buffer. -func (b *VertexBuffer) DestroyHashTable() { +func (b *Tet4VertexBuffer) DestroyHashTable() { // Clear memory. b.hashTable = nil runtime.GC() } -func (b *VertexBuffer) Vertex(i uint32) v3.Vec { +func (b *Tet4VertexBuffer) Vertex(i uint32) v3.Vec { return b.V[i] } diff --git a/render/tet4.go b/render/tet4.go index 4072831b8..44c6068cc 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -36,7 +36,7 @@ type MeshTet4 struct { // Vertex buffer. // All coordinates are unique. // Used to avoid repeating vertices when adding a new tetrahedron. - VBuff *buffer.VertexBuffer + VBuff *buffer.Tet4VertexBuffer } // To get a new mesh and number of its layers along Z-axis. @@ -70,7 +70,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { } // Initialize - t.VBuff = buffer.NewVertexBuffer() + t.VBuff = buffer.NewTet4VertexBuffer() return t } @@ -170,7 +170,7 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { } // To write only required nodes to the file. - vsBuff := buffer.NewVertexBuffer() + vsBuff := buffer.NewTet4VertexBuffer() defer vsBuff.DestroyHashTable() var node0, node1, node2, node3 v3.Vec From 4c593c3d9a076a61f489adfc09238d61f2b11250 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 12:34:15 +0330 Subject: [PATCH 111/775] Rename file --- render/buffer/{tet4vertex.go => tet4vertexbuffer.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename render/buffer/{tet4vertex.go => tet4vertexbuffer.go} (100%) diff --git a/render/buffer/tet4vertex.go b/render/buffer/tet4vertexbuffer.go similarity index 100% rename from render/buffer/tet4vertex.go rename to render/buffer/tet4vertexbuffer.go From de5854daf6cfc8aa5c55393b87aaf503ea9e24d5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 12:35:49 +0330 Subject: [PATCH 112/775] Rename type --- render/buffer/tet4vertexbuffer.go | 15 ++++++++------- render/tet4.go | 6 +++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/render/buffer/tet4vertexbuffer.go b/render/buffer/tet4vertexbuffer.go index 1a7e9d6f7..1660906e9 100644 --- a/render/buffer/tet4vertexbuffer.go +++ b/render/buffer/tet4vertexbuffer.go @@ -6,16 +6,17 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) +// Vertex buffer for 4-node tetrahedra. // To avoid repeating vertices on vertex buffer. -type Tet4VertexBuffer struct { +type Tet4VB struct { // To store index of vertices. Repeated vertices would have the same index. hashTable map[[3]int32]uint32 // To store coordinates of vertices. V []v3.Vec } -func NewTet4VertexBuffer() *Tet4VertexBuffer { - b := Tet4VertexBuffer{ +func NewTet4VB() *Tet4VB { + b := Tet4VB{ hashTable: map[[3]int32]uint32{}, V: []v3.Vec{}, } @@ -26,7 +27,7 @@ func NewTet4VertexBuffer() *Tet4VertexBuffer { // Add vertex to buffer and get vertex ID. // If vertex is already available on the buffer, its ID is just returned. // All vertices would be unique. Not repeated. -func (b *Tet4VertexBuffer) Id(v v3.Vec) uint32 { +func (b *Tet4VB) Id(v v3.Vec) uint32 { // Deduplicate by removing small details and use of epsilon epsilon := float64(0.0001) key := [3]int32{int32((v.X + epsilon) * 1000), int32((v.Y + epsilon) * 1000), int32((v.Z + epsilon) * 1000)} @@ -45,18 +46,18 @@ func (b *Tet4VertexBuffer) Id(v v3.Vec) uint32 { return uint32(b.VertexCount() - 1) } -func (b *Tet4VertexBuffer) VertexCount() int { +func (b *Tet4VB) VertexCount() int { return len(b.V) } // To be called after adding all vertices to the vertex buffer. // Call if you are sure that no new vertex will be added to the vertex buffer. -func (b *Tet4VertexBuffer) DestroyHashTable() { +func (b *Tet4VB) DestroyHashTable() { // Clear memory. b.hashTable = nil runtime.GC() } -func (b *Tet4VertexBuffer) Vertex(i uint32) v3.Vec { +func (b *Tet4VB) Vertex(i uint32) v3.Vec { return b.V[i] } diff --git a/render/tet4.go b/render/tet4.go index 44c6068cc..b40bd9a7c 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -36,7 +36,7 @@ type MeshTet4 struct { // Vertex buffer. // All coordinates are unique. // Used to avoid repeating vertices when adding a new tetrahedron. - VBuff *buffer.Tet4VertexBuffer + VBuff *buffer.Tet4VB } // To get a new mesh and number of its layers along Z-axis. @@ -70,7 +70,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { } // Initialize - t.VBuff = buffer.NewTet4VertexBuffer() + t.VBuff = buffer.NewTet4VB() return t } @@ -170,7 +170,7 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { } // To write only required nodes to the file. - vsBuff := buffer.NewTet4VertexBuffer() + vsBuff := buffer.NewTet4VB() defer vsBuff.DestroyHashTable() var node0, node1, node2, node3 v3.Vec From 7b6dd2835a8e9e5efeb9f51769b174c66587957c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 12:57:24 +0330 Subject: [PATCH 113/775] New index buffer pkg --- render/buffer/tet4indexbuffer.go | 57 ++++++++++++++++++++++++++++++++ render/tet4.go | 32 ++++++------------ 2 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 render/buffer/tet4indexbuffer.go diff --git a/render/buffer/tet4indexbuffer.go b/render/buffer/tet4indexbuffer.go new file mode 100644 index 000000000..1f7922d5f --- /dev/null +++ b/render/buffer/tet4indexbuffer.go @@ -0,0 +1,57 @@ +package buffer + +// Index buffer for 4-node tetrahedra. +type Tet4IB struct { + // Every 4 indices would correspond to a tetrahedron. + // It's kept low-level for performance. + // Tetrahedra are stored by their layer on Z axis. + I [][]uint32 +} + +func NewTet4IB(layerCount int) *Tet4IB { + ib := Tet4IB{ + I: [][]uint32{}, + } + + // Initialize. + ib.I = make([][]uint32, layerCount) + for l := 0; l < layerCount; l++ { + ib.I[l] = make([]uint32, 0) + } + + return &ib +} + +// Layer number and 4 nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (ib *Tet4IB) AddTet4(l int, a, b, c, d uint32) { + ib.I[l] = append(ib.I[l], a, b, c, d) +} + +// Number of layers along the Z axis. +func (ib *Tet4IB) LayerCount() int { + return len(ib.I) +} + +// Number of tetrahedra on a layer. +func (ib *Tet4IB) Tet4CountOnLayer(l int) int { + return len(ib.I[l]) / 4 +} + +// Number of tetrahedra for all layers. +func (ib *Tet4IB) Tet4Count() int { + var count int + for _, l := range ib.I { + count += len(l) / 4 + } + return count +} + +// Layer number is input. +// Tetrahedron index on layer is input. +// Tetrahedron index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (ib *Tet4IB) Tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { + return ib.I[l][i*4], ib.I[l][i*4+1], ib.I[l][i*4+2], ib.I[l][i*4+3] +} diff --git a/render/tet4.go b/render/tet4.go index b40bd9a7c..5ee663221 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -30,12 +30,8 @@ type Tet4 struct { // The element connectivity would be created with unique nodes. type MeshTet4 struct { // Index buffer. - // Every 4 indices would correspond to a tetrahedron. Low-level for performance. - // Tetrahedra are stored by their layer on Z axis. - T [][]uint32 + IBuff *buffer.Tet4IB // Vertex buffer. - // All coordinates are unique. - // Used to avoid repeating vertices when adding a new tetrahedron. VBuff *buffer.Tet4VB } @@ -59,17 +55,12 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { func newMeshTet4(layerCount int) *MeshTet4 { t := &MeshTet4{ - T: nil, + IBuff: nil, VBuff: nil, } // Initialize. - t.T = make([][]uint32, layerCount) - for l := 0; l < layerCount; l++ { - t.T[l] = make([]uint32, 0) - } - - // Initialize + t.IBuff = buffer.NewTet4IB(layerCount) t.VBuff = buffer.NewTet4VB() return t @@ -79,7 +70,7 @@ func newMeshTet4(layerCount int) *MeshTet4 { // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf func (m *MeshTet4) addTet4(l int, a, b, c, d v3.Vec) { - m.T[l] = append(m.T[l], m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) + m.IBuff.AddTet4(l, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) } func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { @@ -96,21 +87,17 @@ func (m *MeshTet4) vertex(i uint32) v3.Vec { // Number of layers along the Z axis. func (m *MeshTet4) layerCount() int { - return len(m.T) + return m.IBuff.LayerCount() } // Number of tetrahedra on a layer. func (m *MeshTet4) tet4CountOnLayer(l int) int { - return len(m.T[l]) / 4 + return m.IBuff.Tet4CountOnLayer(l) } // Number of tetrahedra for all layers. func (m *MeshTet4) tet4Count() int { - var count int - for _, l := range m.T { - count += len(l) / 4 - } - return count + return m.IBuff.Tet4Count() } // Layer number is input. @@ -118,7 +105,7 @@ func (m *MeshTet4) tet4Count() int { // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. func (m *MeshTet4) tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { - return m.T[l][i*4], m.T[l][i*4+1], m.T[l][i*4+2], m.T[l][i*4+3] + return m.IBuff.Tet4Indicies(l, i) } // Layer number is input. @@ -126,7 +113,8 @@ func (m *MeshTet4) tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. func (m *MeshTet4) tet4Vertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { - return m.VBuff.Vertex(m.T[l][i*4]), m.VBuff.Vertex(m.T[l][i*4+1]), m.VBuff.Vertex(m.T[l][i*4+2]), m.VBuff.Vertex(m.T[l][i*4+3]) + idx0, idx1, idx2, idx3 := m.IBuff.Tet4Indicies(l, i) + return m.VBuff.Vertex(idx0), m.VBuff.Vertex(idx1), m.VBuff.Vertex(idx2), m.VBuff.Vertex(idx3) } // Write mesh to ABAQUS or CalculiX `inp` file. From dd8f1e2ae3facb05fc474d0bcfed11345afe11fa Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 13:17:59 +0330 Subject: [PATCH 114/775] Rename --- render/tet4.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index 5ee663221..cb8073b89 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -158,18 +158,18 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { } // To write only required nodes to the file. - vsBuff := buffer.NewTet4VB() - defer vsBuff.DestroyHashTable() + tempVBuff := buffer.NewTet4VB() + defer tempVBuff.DestroyHashTable() var node0, node1, node2, node3 v3.Vec var id0, id1, id2, id3 uint32 for l := layerStart; l < layerEnd; l++ { for i := 0; i < m.tet4CountOnLayer(l); i++ { node0, node1, node2, node3 = m.tet4Vertices(l, i) - id0 = vsBuff.Id(node0) - id1 = vsBuff.Id(node1) - id2 = vsBuff.Id(node2) - id3 = vsBuff.Id(node3) + id0 = tempVBuff.Id(node0) + id1 = tempVBuff.Id(node1) + id2 = tempVBuff.Id(node2) + id3 = tempVBuff.Id(node3) // ID starts from one not zero. _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id0+1, float32(node0.X), float32(node0.Y), float32(node0.Z))) if err != nil { @@ -204,10 +204,10 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { for l := layerStart; l < layerEnd; l++ { for i := 0; i < m.tet4CountOnLayer(l); i++ { node0, node1, node2, node3 = m.tet4Vertices(l, i) - id0 = vsBuff.Id(node0) - id1 = vsBuff.Id(node1) - id2 = vsBuff.Id(node2) - id3 = vsBuff.Id(node3) + id0 = tempVBuff.Id(node0) + id1 = tempVBuff.Id(node1) + id2 = tempVBuff.Id(node2) + id3 = tempVBuff.Id(node3) // ID starts from one not zero. _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, id0+1, id1+1, id2+1, id3+1)) if err != nil { From c68fad83d8786e82fe5e90347b7b59d4f9f1e27f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 13:21:47 +0330 Subject: [PATCH 115/775] Simplify --- render/tet4.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index cb8073b89..1943d1e28 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -54,16 +54,10 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { } func newMeshTet4(layerCount int) *MeshTet4 { - t := &MeshTet4{ - IBuff: nil, - VBuff: nil, + return &MeshTet4{ + IBuff: buffer.NewTet4IB(layerCount), + VBuff: buffer.NewTet4VB(), } - - // Initialize. - t.IBuff = buffer.NewTet4IB(layerCount) - t.VBuff = buffer.NewTet4VB() - - return t } // Layer number and 4 nodes are input. From c92114bf66288b5870f7ae32436cae9e6d408def Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 1 Mar 2023 13:34:57 +0330 Subject: [PATCH 116/775] Comment --- render/tet4.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/tet4.go b/render/tet4.go index 1943d1e28..83e7d8367 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -160,6 +160,7 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { for l := layerStart; l < layerEnd; l++ { for i := 0; i < m.tet4CountOnLayer(l); i++ { node0, node1, node2, node3 = m.tet4Vertices(l, i) + // Get the node IDs. id0 = tempVBuff.Id(node0) id1 = tempVBuff.Id(node1) id2 = tempVBuff.Id(node2) From ba41fadf8feca95737d12d6741242df187a65349 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 2 Mar 2023 14:04:59 +0330 Subject: [PATCH 117/775] Be more like triangle creation code --- render/marchtet4.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index c1ea73aa9..4bee6333d 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -97,18 +97,32 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // create the triangles table := mcTriangleTable[index] count := len(table) / 3 - result := make([]*Tet4, 0, count) + result := make([]*Triangle3, 0, count) for i := 0; i < count; i++ { + t := Triangle3{} + t.V[2] = points[table[i*3+0]] + t.V[1] = points[table[i*3+1]] + t.V[0] = points[table[i*3+2]] + if !t.Degenerate(0) { + result = append(result, &t) + } + } + + // TODO: Create tetrahedra by composing proper tables. + resultTet4 := make([]*Tet4, 0, count) + for _, res := range result { t := Tet4{ V: [4]v3.Vec{}, layer: layerZ, } - t.V[2] = points[table[i*3+0]] - t.V[1] = points[table[i*3+1]] - t.V[0] = points[table[i*3+2]] - result = append(result, &t) + t.V[3] = v3.Vec{X: 0, Y: 0, Z: 0} + t.V[2] = res.V[2] + t.V[1] = res.V[1] + t.V[0] = res.V[0] + resultTet4 = append(resultTet4, &t) } - return result + + return resultTet4 } //----------------------------------------------------------------------------- From 8e0633bfa2f0fe09e84b7f96a5b4475bde3d0177 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 2 Mar 2023 14:18:09 +0330 Subject: [PATCH 118/775] Call `mcToTriangles` directly --- render/marchtet4.go | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index 4bee6333d..b5037fa45 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -73,43 +73,11 @@ func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { //----------------------------------------------------------------------------- func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { - // which of the 0..255 patterns do we have? - index := 0 - for i := 0; i < 8; i++ { - if v[i] < x { - index |= 1 << uint(i) - } - } - // do we have any triangles to create? - if mcEdgeTable[index] == 0 { - return nil - } - // work out the interpolated points on the edges - var points [12]v3.Vec - for i := 0; i < 12; i++ { - bit := 1 << uint(i) - if mcEdgeTable[index]&bit != 0 { - a := mcPairTable[i][0] - b := mcPairTable[i][1] - points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) - } - } - // create the triangles - table := mcTriangleTable[index] - count := len(table) / 3 - result := make([]*Triangle3, 0, count) - for i := 0; i < count; i++ { - t := Triangle3{} - t.V[2] = points[table[i*3+0]] - t.V[1] = points[table[i*3+1]] - t.V[0] = points[table[i*3+2]] - if !t.Degenerate(0) { - result = append(result, &t) - } - } + result := mcToTriangles(p, v, x) // TODO: Create tetrahedra by composing proper tables. - resultTet4 := make([]*Tet4, 0, count) + + resultTet4 := make([]*Tet4, 0, len(result)) for _, res := range result { t := Tet4{ V: [4]v3.Vec{}, From c155e9de863be8c73e16a0c521df14d58d585606 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 12:11:12 +0330 Subject: [PATCH 119/775] New func --- examples/finite_elements/main.go | 36 ++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 6eff5eb41..1ed425bdc 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -15,8 +15,30 @@ import ( "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" + "github.com/deadsy/sdfx/sdf" ) +// Render SDF3 to finite elements. +// Write finite elements to an `inp` file. +// Written file can be used by ABAQUS or CalculiX. +func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { + // Create a mesh out of finite elements. + m, _ := render.NewMeshTet4(s, render.NewMarchingTet4Uniform(200)) + + // Write mesh to file. + err := m.WriteInp(pth) + if err != nil { + return err + } + + // Write just some layers of mesh to a file. + err = m.WriteInpLayers("some-layers-of-"+pth, 0, 32) + if err != nil { + return err + } + return nil +} + func main() { stl := "../../files/teapot.stl" @@ -32,19 +54,7 @@ func main() { log.Fatalf("error: %s", err) } - // Render SDF3 to finite elements. - // Create a mesh out of finite elements. - m, _ := render.NewMeshTet4(teapotSdf, render.NewMarchingTet4Uniform(200)) - - // Write mesh to a file. - // Written file can be used by ABAQUS or CalculiX. - err = m.WriteInp("teapot.inp") - if err != nil { - log.Fatalf("error: %s", err) - } - - // Write just some layers of mesh to a file. - err = m.WriteInpLayers("teapot-some-layers.inp", 0, 32) + err = tet4FiniteElements(teapotSdf, 200, "teapot.inp") if err != nil { log.Fatalf("error: %s", err) } From eda3994d671c731da4e05878fed59504da9d613d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 12:13:35 +0330 Subject: [PATCH 120/775] New func: hex8 --- examples/finite_elements/main.go | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 1ed425bdc..932c91442 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -39,6 +39,27 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { return nil } +// Render SDF3 to finite elements. +// Write finite elements to an `inp` file. +// Written file can be used by ABAQUS or CalculiX. +func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { + // Create a mesh out of finite elements. + m, _ := render.NewMeshHex8(s, render.NewMarchingHex8Uniform(200)) + + // Write mesh to file. + err := m.WriteInp(pth) + if err != nil { + return err + } + + // Write just some layers of mesh to a file. + err = m.WriteInpLayers("some-layers-of-"+pth, 0, 32) + if err != nil { + return err + } + return nil +} + func main() { stl := "../../files/teapot.stl" @@ -54,7 +75,12 @@ func main() { log.Fatalf("error: %s", err) } - err = tet4FiniteElements(teapotSdf, 200, "teapot.inp") + err = tet4FiniteElements(teapotSdf, 200, "teapot-tet4.inp") + if err != nil { + log.Fatalf("error: %s", err) + } + + err = hex8FiniteElements(teapotSdf, 200, "teapot-hex8.inp") if err != nil { log.Fatalf("error: %s", err) } From 596ecff3720717dad2f56aada0be646ca50fd28d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 12:20:44 +0330 Subject: [PATCH 121/775] Comments --- examples/finite_elements/main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 932c91442..2b1f9a54e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -18,6 +18,8 @@ import ( "github.com/deadsy/sdfx/sdf" ) +// 4-node tetrahedral elements. +// // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. @@ -39,6 +41,8 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { return nil } +// 8-node hexahedral elements. +// // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. From a2c056212e837fee5066bdf40d79537190cfd9f2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 12:39:22 +0330 Subject: [PATCH 122/775] Separator line --- render/tet4.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/render/tet4.go b/render/tet4.go index 83e7d8367..415075187 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -24,6 +24,8 @@ type Tet4 struct { layer int } +//----------------------------------------------------------------------------- + // A mesh of tetrahedra with 4 nodes. // A sophisticated data structure for mesh is required to store tetrahedra. // The repeated nodes would be removed. From 0c3bf1a79ca3f9adefb5712bcef89779ce39b8a4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 13:22:46 +0330 Subject: [PATCH 123/775] New files, types, funcs for hex8 --- render/buffer/hex8indexbuffer.go | 58 +++++++ render/hex8.go | 274 +++++++++++++++++++++++++++++++ render/marchhex8.go | 148 +++++++++++++++++ render/render.go | 40 ++++- 4 files changed, 519 insertions(+), 1 deletion(-) create mode 100644 render/buffer/hex8indexbuffer.go create mode 100644 render/hex8.go create mode 100644 render/marchhex8.go diff --git a/render/buffer/hex8indexbuffer.go b/render/buffer/hex8indexbuffer.go new file mode 100644 index 000000000..498ba539a --- /dev/null +++ b/render/buffer/hex8indexbuffer.go @@ -0,0 +1,58 @@ +package buffer + +// Index buffer for 8-node hexahedra. +type Hex8IB struct { + // Every 8 indices would correspond to a hexahedron. + // It's kept low-level for performance. + // Tetrahedra are stored by their layer on Z axis. + I [][]uint32 +} + +func NewHex8IB(layerCount int) *Hex8IB { + ib := Hex8IB{ + I: [][]uint32{}, + } + + // Initialize. + ib.I = make([][]uint32, layerCount) + for l := 0; l < layerCount; l++ { + ib.I[l] = make([]uint32, 0) + } + + return &ib +} + +// Add a finite element to buffer. +// Layer number and nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (ib *Hex8IB) AddFE(l int, n0, n1, n2, n3, n4, n5, n6, n7 uint32) { + ib.I[l] = append(ib.I[l], n0, n1, n2, n3, n4, n5, n6, n7) +} + +// Number of layers along the Z axis. +func (ib *Hex8IB) LayerCount() int { + return len(ib.I) +} + +// Number of finite elements on a layer. +func (ib *Hex8IB) FECountOnLayer(l int) int { + return len(ib.I[l]) / 8 +} + +// Number of finite elements for all layers. +func (ib *Hex8IB) FECount() int { + var count int + for _, l := range ib.I { + count += len(l) / 8 + } + return count +} + +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of FE on layer. +// Don't return error to increase performance. +func (ib *Hex8IB) FEIndicies(l, i int) (uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32) { + return ib.I[l][i*8], ib.I[l][i*8+1], ib.I[l][i*8+2], ib.I[l][i*8+3], ib.I[l][i*8+4], ib.I[l][i*8+5], ib.I[l][i*8+6], ib.I[l][i*8+7] +} diff --git a/render/hex8.go b/render/hex8.go new file mode 100644 index 000000000..9ba2d65f4 --- /dev/null +++ b/render/hex8.go @@ -0,0 +1,274 @@ +package render + +import ( + "fmt" + "os" + "sync" + "time" + + "github.com/deadsy/sdfx/render/buffer" + "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// Hex8 is a 3D hexahedron consisting of 8 nodes. +// It's a kind of finite element, FE. +// https://en.wikipedia.org/wiki/Hexahedron +type Hex8 struct { + // Coordinates of 8 corner nodes or vertices. + V [8]v3.Vec + // The layer to which tetrahedron belongs. Layers are along Z axis. + // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store layer along Z axis. + // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. + // Sampling/marching algorithm is expected to return the layer to which a finite element belongs. + layer int +} + +//----------------------------------------------------------------------------- + +// A mesh of 8-node hexahedra. +// A sophisticated data structure for mesh is required. +// The repeated nodes would be removed. +// The element connectivity would be created with unique nodes. +type MeshHex8 struct { + // Index buffer. + IBuff *buffer.Hex8IB + // Vertex buffer. + VBuff *buffer.Tet4VB +} + +// To get a new mesh and number of its layers along Z-axis. +func NewMeshHex8(s sdf.SDF3, r RenderHex8) (*MeshHex8, int) { + hex8s := ToHex8(s, r) + + _, _, layerCountZ := r.LayerCounts(s) + + m := newMeshHex8(layerCountZ) + + // Fill out the mesh with finite elements. + for _, t := range hex8s { + m.addFE(t.layer, t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7]) + } + + defer m.VBuff.DestroyHashTable() + + return m, layerCountZ +} + +func newMeshHex8(layerCount int) *MeshHex8 { + return &MeshHex8{ + IBuff: buffer.NewHex8IB(layerCount), + VBuff: buffer.NewTet4VB(), + } +} + +// Add a finite element to mesh. +// Layer number and nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (m *MeshHex8) addFE(l int, n0, n1, n2, n3, n4, n5, n6, n7 v3.Vec) { + m.IBuff.AddFE(l, m.addVertex(n0), m.addVertex(n1), m.addVertex(n2), m.addVertex(n3), m.addVertex(n4), m.addVertex(n5), m.addVertex(n6), m.addVertex(n7)) +} + +func (m *MeshHex8) addVertex(vert v3.Vec) uint32 { + return m.VBuff.Id(vert) +} + +func (m *MeshHex8) vertexCount() int { + return m.VBuff.VertexCount() +} + +func (m *MeshHex8) vertex(i uint32) v3.Vec { + return m.VBuff.Vertex(i) +} + +// Number of layers along the Z axis. +func (m *MeshHex8) layerCount() int { + return m.IBuff.LayerCount() +} + +// Number of finite elements on a layer. +func (m *MeshHex8) FECountOnLayer(l int) int { + return m.IBuff.FECountOnLayer(l) +} + +// Number of finite elements for all layers. +func (m *MeshHex8) FECount() int { + return m.IBuff.FECount() +} + +// Get a finite element. +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *MeshHex8) FEIndicies(l, i int) (uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32) { + return m.IBuff.FEIndicies(l, i) +} + +// Get a finite element. +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *MeshHex8) FEVertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec) { + idx0, idx1, idx2, idx3, idx4, idx5, idx6, idx7 := m.IBuff.FEIndicies(l, i) + return m.VBuff.Vertex(idx0), m.VBuff.Vertex(idx1), m.VBuff.Vertex(idx2), m.VBuff.Vertex(idx3), + m.VBuff.Vertex(idx4), m.VBuff.Vertex(idx5), m.VBuff.Vertex(idx6), m.VBuff.Vertex(idx7) +} + +// Write mesh to ABAQUS or CalculiX `inp` file. +func (m *MeshHex8) WriteInp(path string) error { + return m.WriteInpLayers(path, 0, m.layerCount()) +} + +// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +// Result would include start layer. +// Result would exclude end layer. +func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { + if 0 <= layerStart && layerStart < layerEnd && layerEnd <= m.layerCount() { + // Good. + } else { + return fmt.Errorf("start or end layer is beyond range") + } + + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + + // Write headers. + + _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") + if err != nil { + return err + } + + _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") + if err != nil { + return err + } + + // Write nodes. + + _, err = f.WriteString("*NODE\n") + if err != nil { + return err + } + + // To write only required nodes to the file. + tempVBuff := buffer.NewTet4VB() + defer tempVBuff.DestroyHashTable() + + var node0, node1, node2, node3, node4, node5, node6, node7 v3.Vec + var id0, id1, id2, id3, id4, id5, id6, id7 uint32 + for l := layerStart; l < layerEnd; l++ { + for i := 0; i < m.FECountOnLayer(l); i++ { + node0, node1, node2, node3, node4, node5, node6, node7 = m.FEVertices(l, i) + // Get the node IDs. + id0 = tempVBuff.Id(node0) + id1 = tempVBuff.Id(node1) + id2 = tempVBuff.Id(node2) + id3 = tempVBuff.Id(node3) + id4 = tempVBuff.Id(node4) + id5 = tempVBuff.Id(node5) + id6 = tempVBuff.Id(node6) + id7 = tempVBuff.Id(node7) + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id0+1, float32(node0.X), float32(node0.Y), float32(node0.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id1+1, float32(node1.X), float32(node1.Y), float32(node1.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id2+1, float32(node2.X), float32(node2.Y), float32(node2.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id3+1, float32(node3.X), float32(node3.Y), float32(node3.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id4+1, float32(node4.X), float32(node4.Y), float32(node4.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id5+1, float32(node5.X), float32(node5.Y), float32(node5.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id6+1, float32(node6.X), float32(node6.Y), float32(node6.Z))) + if err != nil { + return err + } + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id7+1, float32(node7.X), float32(node7.Y), float32(node7.Z))) + if err != nil { + return err + } + } + } + + // Write elements. + + _, err = f.WriteString("*ELEMENT, TYPE=C3D8, ELSET=Eall\n") + if err != nil { + return err + } + + var eleID uint32 + for l := layerStart; l < layerEnd; l++ { + for i := 0; i < m.FECountOnLayer(l); i++ { + node0, node1, node2, node3, node4, node5, node6, node7 = m.FEVertices(l, i) + id0 = tempVBuff.Id(node0) + id1 = tempVBuff.Id(node1) + id2 = tempVBuff.Id(node2) + id3 = tempVBuff.Id(node3) + id4 = tempVBuff.Id(node4) + id5 = tempVBuff.Id(node5) + id6 = tempVBuff.Id(node6) + id7 = tempVBuff.Id(node7) + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, id0+1, id1+1, id2+1, id3+1, id4+1, id5+1, id6+1, id7+1)) + if err != nil { + return err + } + eleID++ + } + } + + return nil +} + +//----------------------------------------------------------------------------- + +// writeHex8 writes a stream of finite elements, in the shape of 8-node hexahedra, to an array. +func writeHex8(wg *sync.WaitGroup, hex8s *[]Hex8) chan<- []*Hex8 { + // External code writes tetrahedra to this channel. + // This goroutine reads the channel and stores tetrahedra. + c := make(chan []*Hex8) + + wg.Add(1) + go func() { + defer wg.Done() + // read finite elements from the channel and handle them + for ts := range c { + for _, t := range ts { + *hex8s = append(*hex8s, *t) + } + } + }() + + return c +} + +//----------------------------------------------------------------------------- diff --git a/render/marchhex8.go b/render/marchhex8.go new file mode 100644 index 000000000..79cd747d4 --- /dev/null +++ b/render/marchhex8.go @@ -0,0 +1,148 @@ +package render + +import ( + "fmt" + + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +//----------------------------------------------------------------------------- + +func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { + + var tetrahedra []*Hex8 + size := box.Size() + base := box.Min + steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) + inc := size.Div(conv.V3iToV3(steps)) + + // start the evaluation routines + evalRoutines() + + // create the SDF layer cache + l := newLayerYZ(base, inc, steps) + // evaluate the SDF for x = 0 + l.Evaluate(s, 0) + + nx, ny, nz := steps.X, steps.Y, steps.Z + dx, dy, dz := inc.X, inc.Y, inc.Z + + var p v3.Vec + p.X = base.X + for x := 0; x < nx; x++ { + // read the x + 1 layer + l.Evaluate(s, x+1) + // process all cubes in the x and x + 1 layers + p.Y = base.Y + for y := 0; y < ny; y++ { + p.Z = base.Z + for z := 0; z < nz; z++ { + x0, y0, z0 := p.X, p.Y, p.Z + x1, y1, z1 := x0+dx, y0+dy, z0+dz + corners := [8]v3.Vec{ + {x0, y0, z0}, + {x1, y0, z0}, + {x1, y1, z0}, + {x0, y1, z0}, + {x0, y0, z1}, + {x1, y0, z1}, + {x1, y1, z1}, + {x0, y1, z1}} + values := [8]float64{ + l.Get(0, y, z), + l.Get(1, y, z), + l.Get(1, y+1, z), + l.Get(0, y+1, z), + l.Get(0, y, z+1), + l.Get(1, y, z+1), + l.Get(1, y+1, z+1), + l.Get(0, y+1, z+1)} + tetrahedra = append(tetrahedra, mcToHex8(corners, values, 0, z)...) + p.Z += dz + } + p.Y += dy + } + p.X += dx + } + + return tetrahedra +} + +//----------------------------------------------------------------------------- + +func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { + result := mcToTriangles(p, v, x) + + // TODO: Create finite elements properly. + + resultFE := make([]*Hex8, 0, len(result)) + for _, res := range result { + fe := Hex8{ + V: [8]v3.Vec{}, + layer: layerZ, + } + fe.V[2] = res.V[2] + fe.V[1] = res.V[1] + fe.V[0] = res.V[0] + resultFE = append(resultFE, &fe) + } + + return resultFE +} + +//----------------------------------------------------------------------------- + +// MarchingHex8Uniform renders using marching cubes with uniform space sampling. +type MarchingHex8Uniform struct { + meshCells int // number of cells on the longest axis of bounding box. e.g 200 +} + +// NewMarchingHex8Uniform returns a RenderHex8 object. +func NewMarchingHex8Uniform(meshCells int) *MarchingHex8Uniform { + return &MarchingHex8Uniform{ + meshCells: meshCells, + } +} + +// Info returns a string describing the rendered volume. +func (r *MarchingHex8Uniform) Info(s sdf.SDF3) string { + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + cells := conv.V3ToV3i(bb1Size) + return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) +} + +// To get the layer counts which are consistent with loops of marching algorithm. +func (r *MarchingHex8Uniform) LayerCounts(s sdf.SDF3) (int, int, int) { + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + size := bb.Size() + steps := conv.V3ToV3i(size.DivScalar(meshInc).Ceil()) + return steps.X, steps.Y, steps.Z +} + +// Render produces a finite elements mesh over the bounding volume of an sdf3. +// Finite elements are in the shape of hexahedra. +func (r *MarchingHex8Uniform) Render(s sdf.SDF3, output chan<- []*Hex8) { + // work out the region we will sample + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + output <- marchingCubesHex8(s, bb, meshInc) +} + +//----------------------------------------------------------------------------- diff --git a/render/render.go b/render/render.go index af2c0b5b8..147023da7 100644 --- a/render/render.go +++ b/render/render.go @@ -30,13 +30,21 @@ type Render2 interface { } // RenderTet4 renders a finite element mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of tetrahedra, each with 4 nodes. +// Finite elements are in the shape of 4-node tetrahedra. type RenderTet4 interface { Render(sdf3 sdf.SDF3, output chan<- []*Tet4) Info(sdf3 sdf.SDF3) string LayerCounts(sdf3 sdf.SDF3) (int, int, int) } +// RenderHex8 renders a finite element mesh over the bounding volume of an sdf3. +// Finite elements are in the shape of 8-node hexahedra. +type RenderHex8 interface { + Render(sdf3 sdf.SDF3, output chan<- []*Hex8) + Info(sdf3 sdf.SDF3) string + LayerCounts(sdf3 sdf.SDF3) (int, int, int) +} + //----------------------------------------------------------------------------- // ToTriangles renders an SDF3 to a triangle mesh. @@ -90,6 +98,36 @@ func ToTet4( //----------------------------------------------------------------------------- +// ToHex8 renders an SDF3 to finite elements in the shape of 8-node hexahedra. +func ToHex8( + s sdf.SDF3, // sdf3 to render + r RenderHex8, // rendering method +) []Hex8 { + fmt.Printf("rendering %s\n", r.Info(s)) + + layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) + fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) + + // Will be filled by the rendering. + hex8s := make([]Hex8, 0) + + var wg sync.WaitGroup + + // Get the channel to be written to. + output := writeHex8(&wg, &hex8s) + + // run the renderer + r.Render(s, output) + // stop the writer reading on the channel + close(output) + // wait for the file write to complete + wg.Wait() + + return hex8s +} + +//----------------------------------------------------------------------------- + // ToSTL renders an SDF3 to an STL file. func ToSTL( s sdf.SDF3, // sdf3 to render From 8c0f72f56a4661de8fcf3fa6f4fb5c9b35aa64fa Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 13:23:40 +0330 Subject: [PATCH 124/775] Rename file --- render/buffer/{tet4vertexbuffer.go => vertexbuffer.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename render/buffer/{tet4vertexbuffer.go => vertexbuffer.go} (100%) diff --git a/render/buffer/tet4vertexbuffer.go b/render/buffer/vertexbuffer.go similarity index 100% rename from render/buffer/tet4vertexbuffer.go rename to render/buffer/vertexbuffer.go From ce93d4f599fde6686978545c82c33720937d4831 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 13:28:04 +0330 Subject: [PATCH 125/775] Vertex buffer is the same for tet4 and hex8 --- render/buffer/vertexbuffer.go | 21 +++++++++++---------- render/hex8.go | 6 +++--- render/tet4.go | 6 +++--- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/render/buffer/vertexbuffer.go b/render/buffer/vertexbuffer.go index 1660906e9..b9f1461a9 100644 --- a/render/buffer/vertexbuffer.go +++ b/render/buffer/vertexbuffer.go @@ -6,17 +6,18 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -// Vertex buffer for 4-node tetrahedra. -// To avoid repeating vertices on vertex buffer. -type Tet4VB struct { +// Vertex buffer for finite elements. +// Vertex buffer avoids repeating vertices by a hash table. +// The same vertex buffer is used for 4-node tetrahedra, 8-node hexahedra, and others. +type VB struct { // To store index of vertices. Repeated vertices would have the same index. hashTable map[[3]int32]uint32 // To store coordinates of vertices. V []v3.Vec } -func NewTet4VB() *Tet4VB { - b := Tet4VB{ +func NewVB() *VB { + b := VB{ hashTable: map[[3]int32]uint32{}, V: []v3.Vec{}, } @@ -26,8 +27,8 @@ func NewTet4VB() *Tet4VB { // Add vertex to buffer and get vertex ID. // If vertex is already available on the buffer, its ID is just returned. -// All vertices would be unique. Not repeated. -func (b *Tet4VB) Id(v v3.Vec) uint32 { +// So, all vertices will be unique. Not repeated. +func (b *VB) Id(v v3.Vec) uint32 { // Deduplicate by removing small details and use of epsilon epsilon := float64(0.0001) key := [3]int32{int32((v.X + epsilon) * 1000), int32((v.Y + epsilon) * 1000), int32((v.Z + epsilon) * 1000)} @@ -46,18 +47,18 @@ func (b *Tet4VB) Id(v v3.Vec) uint32 { return uint32(b.VertexCount() - 1) } -func (b *Tet4VB) VertexCount() int { +func (b *VB) VertexCount() int { return len(b.V) } // To be called after adding all vertices to the vertex buffer. // Call if you are sure that no new vertex will be added to the vertex buffer. -func (b *Tet4VB) DestroyHashTable() { +func (b *VB) DestroyHashTable() { // Clear memory. b.hashTable = nil runtime.GC() } -func (b *Tet4VB) Vertex(i uint32) v3.Vec { +func (b *VB) Vertex(i uint32) v3.Vec { return b.V[i] } diff --git a/render/hex8.go b/render/hex8.go index 9ba2d65f4..249f0f1e1 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -34,7 +34,7 @@ type MeshHex8 struct { // Index buffer. IBuff *buffer.Hex8IB // Vertex buffer. - VBuff *buffer.Tet4VB + VBuff *buffer.VB } // To get a new mesh and number of its layers along Z-axis. @@ -58,7 +58,7 @@ func NewMeshHex8(s sdf.SDF3, r RenderHex8) (*MeshHex8, int) { func newMeshHex8(layerCount int) *MeshHex8 { return &MeshHex8{ IBuff: buffer.NewHex8IB(layerCount), - VBuff: buffer.NewTet4VB(), + VBuff: buffer.NewVB(), } } @@ -158,7 +158,7 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { } // To write only required nodes to the file. - tempVBuff := buffer.NewTet4VB() + tempVBuff := buffer.NewVB() defer tempVBuff.DestroyHashTable() var node0, node1, node2, node3, node4, node5, node6, node7 v3.Vec diff --git a/render/tet4.go b/render/tet4.go index 415075187..e51b0bb40 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -34,7 +34,7 @@ type MeshTet4 struct { // Index buffer. IBuff *buffer.Tet4IB // Vertex buffer. - VBuff *buffer.Tet4VB + VBuff *buffer.VB } // To get a new mesh and number of its layers along Z-axis. @@ -58,7 +58,7 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { func newMeshTet4(layerCount int) *MeshTet4 { return &MeshTet4{ IBuff: buffer.NewTet4IB(layerCount), - VBuff: buffer.NewTet4VB(), + VBuff: buffer.NewVB(), } } @@ -154,7 +154,7 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { } // To write only required nodes to the file. - tempVBuff := buffer.NewTet4VB() + tempVBuff := buffer.NewVB() defer tempVBuff.DestroyHashTable() var node0, node1, node2, node3 v3.Vec From 7b6459744f1c32c9a2222727d6dc4d24c36d857e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 13:32:55 +0330 Subject: [PATCH 126/775] Rename: more consistent --- render/buffer/tet4indexbuffer.go | 6 +++--- render/hex8.go | 16 ++++++++-------- render/tet4.go | 33 +++++++++++++++++--------------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/render/buffer/tet4indexbuffer.go b/render/buffer/tet4indexbuffer.go index 1f7922d5f..4e0bafda1 100644 --- a/render/buffer/tet4indexbuffer.go +++ b/render/buffer/tet4indexbuffer.go @@ -35,12 +35,12 @@ func (ib *Tet4IB) LayerCount() int { } // Number of tetrahedra on a layer. -func (ib *Tet4IB) Tet4CountOnLayer(l int) int { +func (ib *Tet4IB) FECountOnLayer(l int) int { return len(ib.I[l]) / 4 } // Number of tetrahedra for all layers. -func (ib *Tet4IB) Tet4Count() int { +func (ib *Tet4IB) FECount() int { var count int for _, l := range ib.I { count += len(l) / 4 @@ -52,6 +52,6 @@ func (ib *Tet4IB) Tet4Count() int { // Tetrahedron index on layer is input. // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (ib *Tet4IB) Tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { +func (ib *Tet4IB) FEIndicies(l, i int) (uint32, uint32, uint32, uint32) { return ib.I[l][i*4], ib.I[l][i*4+1], ib.I[l][i*4+2], ib.I[l][i*4+3] } diff --git a/render/hex8.go b/render/hex8.go index 249f0f1e1..8b6518477 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -88,12 +88,12 @@ func (m *MeshHex8) layerCount() int { } // Number of finite elements on a layer. -func (m *MeshHex8) FECountOnLayer(l int) int { +func (m *MeshHex8) feCountOnLayer(l int) int { return m.IBuff.FECountOnLayer(l) } // Number of finite elements for all layers. -func (m *MeshHex8) FECount() int { +func (m *MeshHex8) feCount() int { return m.IBuff.FECount() } @@ -102,7 +102,7 @@ func (m *MeshHex8) FECount() int { // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex8) FEIndicies(l, i int) (uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32) { +func (m *MeshHex8) feIndicies(l, i int) (uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32) { return m.IBuff.FEIndicies(l, i) } @@ -111,7 +111,7 @@ func (m *MeshHex8) FEIndicies(l, i int) (uint32, uint32, uint32, uint32, uint32, // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex8) FEVertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec) { +func (m *MeshHex8) feVertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec) { idx0, idx1, idx2, idx3, idx4, idx5, idx6, idx7 := m.IBuff.FEIndicies(l, i) return m.VBuff.Vertex(idx0), m.VBuff.Vertex(idx1), m.VBuff.Vertex(idx2), m.VBuff.Vertex(idx3), m.VBuff.Vertex(idx4), m.VBuff.Vertex(idx5), m.VBuff.Vertex(idx6), m.VBuff.Vertex(idx7) @@ -164,8 +164,8 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { var node0, node1, node2, node3, node4, node5, node6, node7 v3.Vec var id0, id1, id2, id3, id4, id5, id6, id7 uint32 for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.FECountOnLayer(l); i++ { - node0, node1, node2, node3, node4, node5, node6, node7 = m.FEVertices(l, i) + for i := 0; i < m.feCountOnLayer(l); i++ { + node0, node1, node2, node3, node4, node5, node6, node7 = m.feVertices(l, i) // Get the node IDs. id0 = tempVBuff.Id(node0) id1 = tempVBuff.Id(node1) @@ -227,8 +227,8 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { var eleID uint32 for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.FECountOnLayer(l); i++ { - node0, node1, node2, node3, node4, node5, node6, node7 = m.FEVertices(l, i) + for i := 0; i < m.feCountOnLayer(l); i++ { + node0, node1, node2, node3, node4, node5, node6, node7 = m.feVertices(l, i) id0 = tempVBuff.Id(node0) id1 = tempVBuff.Id(node1) id2 = tempVBuff.Id(node2) diff --git a/render/tet4.go b/render/tet4.go index e51b0bb40..3fa21edb9 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -47,7 +47,7 @@ func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { // Fill out the mesh with finite elements. for _, t := range tet4s { - m.addTet4(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) + m.addFE(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) } defer m.VBuff.DestroyHashTable() @@ -62,10 +62,11 @@ func newMeshTet4(layerCount int) *MeshTet4 { } } -// Layer number and 4 nodes are input. +// Add a finite element. +// Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) addTet4(l int, a, b, c, d v3.Vec) { +func (m *MeshTet4) addFE(l int, a, b, c, d v3.Vec) { m.IBuff.AddTet4(l, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) } @@ -87,29 +88,31 @@ func (m *MeshTet4) layerCount() int { } // Number of tetrahedra on a layer. -func (m *MeshTet4) tet4CountOnLayer(l int) int { - return m.IBuff.Tet4CountOnLayer(l) +func (m *MeshTet4) feCountOnLayer(l int) int { + return m.IBuff.FECountOnLayer(l) } // Number of tetrahedra for all layers. -func (m *MeshTet4) tet4Count() int { - return m.IBuff.Tet4Count() +func (m *MeshTet4) feCount() int { + return m.IBuff.FECount() } +// Get a finite element. // Layer number is input. // Tetrahedron index on layer is input. // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) tet4Indicies(l, i int) (uint32, uint32, uint32, uint32) { - return m.IBuff.Tet4Indicies(l, i) +func (m *MeshTet4) feIndicies(l, i int) (uint32, uint32, uint32, uint32) { + return m.IBuff.FEIndicies(l, i) } +// Get a finite element. // Layer number is input. // Tetrahedron index on layer is input. // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) tet4Vertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { - idx0, idx1, idx2, idx3 := m.IBuff.Tet4Indicies(l, i) +func (m *MeshTet4) feVertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { + idx0, idx1, idx2, idx3 := m.IBuff.FEIndicies(l, i) return m.VBuff.Vertex(idx0), m.VBuff.Vertex(idx1), m.VBuff.Vertex(idx2), m.VBuff.Vertex(idx3) } @@ -160,8 +163,8 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { var node0, node1, node2, node3 v3.Vec var id0, id1, id2, id3 uint32 for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.tet4CountOnLayer(l); i++ { - node0, node1, node2, node3 = m.tet4Vertices(l, i) + for i := 0; i < m.feCountOnLayer(l); i++ { + node0, node1, node2, node3 = m.feVertices(l, i) // Get the node IDs. id0 = tempVBuff.Id(node0) id1 = tempVBuff.Id(node1) @@ -199,8 +202,8 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { var eleID uint32 for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.tet4CountOnLayer(l); i++ { - node0, node1, node2, node3 = m.tet4Vertices(l, i) + for i := 0; i < m.feCountOnLayer(l); i++ { + node0, node1, node2, node3 = m.feVertices(l, i) id0 = tempVBuff.Id(node0) id1 = tempVBuff.Id(node1) id2 = tempVBuff.Id(node2) From ad9b56991a3816c87cb6ff4489136afa6c1cbdc2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 13:47:28 +0330 Subject: [PATCH 127/775] Create hex8 if all 8 values are non-positive --- render/marchhex8.go | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/render/marchhex8.go b/render/marchhex8.go index 79cd747d4..41ed45839 100644 --- a/render/marchhex8.go +++ b/render/marchhex8.go @@ -73,19 +73,35 @@ func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { //----------------------------------------------------------------------------- func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { - result := mcToTriangles(p, v, x) - - // TODO: Create finite elements properly. + // Create a finite element if all 8 values are negative. + // Finite element is inside the 3D model if all values are negative. + // Of course, some spaces are missed by this approach. + // + // TODO: Come up with a more sophisticated approach? + + resultFE := make([]*Hex8, 0) + + anyPositive := false + for i := 0; i < 8; i++ { + if v[i] > 0 { + anyPositive = true + break + } + } - resultFE := make([]*Hex8, 0, len(result)) - for _, res := range result { + if !anyPositive { fe := Hex8{ V: [8]v3.Vec{}, layer: layerZ, } - fe.V[2] = res.V[2] - fe.V[1] = res.V[1] - fe.V[0] = res.V[0] + fe.V[7] = p[7] + fe.V[6] = p[6] + fe.V[5] = p[5] + fe.V[4] = p[4] + fe.V[3] = p[3] + fe.V[2] = p[2] + fe.V[1] = p[1] + fe.V[0] = p[0] resultFE = append(resultFE, &fe) } From d71e4511c71f9336b580a4853fb17f6c40337cc1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 13:49:19 +0330 Subject: [PATCH 128/775] Rename & comment --- render/marchhex8.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/render/marchhex8.go b/render/marchhex8.go index 41ed45839..004577480 100644 --- a/render/marchhex8.go +++ b/render/marchhex8.go @@ -73,13 +73,7 @@ func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { //----------------------------------------------------------------------------- func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { - // Create a finite element if all 8 values are negative. - // Finite element is inside the 3D model if all values are negative. - // Of course, some spaces are missed by this approach. - // - // TODO: Come up with a more sophisticated approach? - - resultFE := make([]*Hex8, 0) + result := make([]*Hex8, 0) anyPositive := false for i := 0; i < 8; i++ { @@ -89,6 +83,12 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { } } + // Create a finite element if all 8 values are non-positive. + // Finite element is inside the 3D model if all values are non-positive. + // Of course, some spaces are missed by this approach. + // + // TODO: Come up with a more sophisticated approach? + if !anyPositive { fe := Hex8{ V: [8]v3.Vec{}, @@ -102,10 +102,10 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { fe.V[2] = p[2] fe.V[1] = p[1] fe.V[0] = p[0] - resultFE = append(resultFE, &fe) + result = append(result, &fe) } - return resultFE + return result } //----------------------------------------------------------------------------- From 28e7e30a66d1ed9f82c222de2b6fee93f259cd7d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 13:54:06 +0330 Subject: [PATCH 129/775] Rename to be consistent --- render/hex8.go | 6 +++--- render/tet4.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/render/hex8.go b/render/hex8.go index 8b6518477..34b0c9a85 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -39,15 +39,15 @@ type MeshHex8 struct { // To get a new mesh and number of its layers along Z-axis. func NewMeshHex8(s sdf.SDF3, r RenderHex8) (*MeshHex8, int) { - hex8s := ToHex8(s, r) + fes := ToHex8(s, r) _, _, layerCountZ := r.LayerCounts(s) m := newMeshHex8(layerCountZ) // Fill out the mesh with finite elements. - for _, t := range hex8s { - m.addFE(t.layer, t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7]) + for _, fe := range fes { + m.addFE(fe.layer, fe.V[0], fe.V[1], fe.V[2], fe.V[3], fe.V[4], fe.V[5], fe.V[6], fe.V[7]) } defer m.VBuff.DestroyHashTable() diff --git a/render/tet4.go b/render/tet4.go index 3fa21edb9..6d258722a 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -39,15 +39,15 @@ type MeshTet4 struct { // To get a new mesh and number of its layers along Z-axis. func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { - tet4s := ToTet4(s, r) + fes := ToTet4(s, r) _, _, layerCountZ := r.LayerCounts(s) m := newMeshTet4(layerCountZ) // Fill out the mesh with finite elements. - for _, t := range tet4s { - m.addFE(t.layer, t.V[0], t.V[1], t.V[2], t.V[3]) + for _, fe := range fes { + m.addFE(fe.layer, fe.V[0], fe.V[1], fe.V[2], fe.V[3]) } defer m.VBuff.DestroyHashTable() From e269c6e2b1d5ed9af74c3bc0651ec51320ad529a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 14:19:16 +0330 Subject: [PATCH 130/775] Use [8] array rather than 8 vars, it may go to 20 --- render/buffer/hex8indexbuffer.go | 12 ++-- render/hex8.go | 105 +++++++++++-------------------- 2 files changed, 46 insertions(+), 71 deletions(-) diff --git a/render/buffer/hex8indexbuffer.go b/render/buffer/hex8indexbuffer.go index 498ba539a..a713eb841 100644 --- a/render/buffer/hex8indexbuffer.go +++ b/render/buffer/hex8indexbuffer.go @@ -26,8 +26,8 @@ func NewHex8IB(layerCount int) *Hex8IB { // Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (ib *Hex8IB) AddFE(l int, n0, n1, n2, n3, n4, n5, n6, n7 uint32) { - ib.I[l] = append(ib.I[l], n0, n1, n2, n3, n4, n5, n6, n7) +func (ib *Hex8IB) AddFE(l int, nodes [8]uint32) { + ib.I[l] = append(ib.I[l], nodes[:]...) } // Number of layers along the Z axis. @@ -53,6 +53,10 @@ func (ib *Hex8IB) FECount() int { // FE index on layer is input. // FE index could be from 0 to number of FE on layer. // Don't return error to increase performance. -func (ib *Hex8IB) FEIndicies(l, i int) (uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32) { - return ib.I[l][i*8], ib.I[l][i*8+1], ib.I[l][i*8+2], ib.I[l][i*8+3], ib.I[l][i*8+4], ib.I[l][i*8+5], ib.I[l][i*8+6], ib.I[l][i*8+7] +func (ib *Hex8IB) FEIndicies(l, i int) [8]uint32 { + indices := [8]uint32{} + for n := 0; n < 8; n++ { + indices[n] = ib.I[l][i*8+n] + } + return indices } diff --git a/render/hex8.go b/render/hex8.go index 34b0c9a85..26601a1d9 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -47,7 +47,11 @@ func NewMeshHex8(s sdf.SDF3, r RenderHex8) (*MeshHex8, int) { // Fill out the mesh with finite elements. for _, fe := range fes { - m.addFE(fe.layer, fe.V[0], fe.V[1], fe.V[2], fe.V[3], fe.V[4], fe.V[5], fe.V[6], fe.V[7]) + nodes := [8]v3.Vec{} + for n := 0; n < 8; n++ { + nodes[n] = fe.V[n] + } + m.addFE(fe.layer, nodes) } defer m.VBuff.DestroyHashTable() @@ -66,8 +70,12 @@ func newMeshHex8(layerCount int) *MeshHex8 { // Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshHex8) addFE(l int, n0, n1, n2, n3, n4, n5, n6, n7 v3.Vec) { - m.IBuff.AddFE(l, m.addVertex(n0), m.addVertex(n1), m.addVertex(n2), m.addVertex(n3), m.addVertex(n4), m.addVertex(n5), m.addVertex(n6), m.addVertex(n7)) +func (m *MeshHex8) addFE(l int, nodes [8]v3.Vec) { + indices := [8]uint32{} + for n := 0; n < 8; n++ { + indices[n] = m.addVertex(nodes[n]) + } + m.IBuff.AddFE(l, indices) } func (m *MeshHex8) addVertex(vert v3.Vec) uint32 { @@ -102,7 +110,7 @@ func (m *MeshHex8) feCount() int { // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex8) feIndicies(l, i int) (uint32, uint32, uint32, uint32, uint32, uint32, uint32, uint32) { +func (m *MeshHex8) feIndicies(l, i int) [8]uint32 { return m.IBuff.FEIndicies(l, i) } @@ -111,10 +119,13 @@ func (m *MeshHex8) feIndicies(l, i int) (uint32, uint32, uint32, uint32, uint32, // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex8) feVertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec, v3.Vec) { - idx0, idx1, idx2, idx3, idx4, idx5, idx6, idx7 := m.IBuff.FEIndicies(l, i) - return m.VBuff.Vertex(idx0), m.VBuff.Vertex(idx1), m.VBuff.Vertex(idx2), m.VBuff.Vertex(idx3), - m.VBuff.Vertex(idx4), m.VBuff.Vertex(idx5), m.VBuff.Vertex(idx6), m.VBuff.Vertex(idx7) +func (m *MeshHex8) feVertices(l, i int) [8]v3.Vec { + indices := m.IBuff.FEIndicies(l, i) + vertices := [8]v3.Vec{} + for n := 0; n < 8; n++ { + vertices[n] = m.VBuff.Vertex(indices[n]) + } + return vertices } // Write mesh to ABAQUS or CalculiX `inp` file. @@ -161,59 +172,23 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { tempVBuff := buffer.NewVB() defer tempVBuff.DestroyHashTable() - var node0, node1, node2, node3, node4, node5, node6, node7 v3.Vec - var id0, id1, id2, id3, id4, id5, id6, id7 uint32 + nodes := [8]v3.Vec{} + ids := [8]uint32{} for l := layerStart; l < layerEnd; l++ { for i := 0; i < m.feCountOnLayer(l); i++ { - node0, node1, node2, node3, node4, node5, node6, node7 = m.feVertices(l, i) // Get the node IDs. - id0 = tempVBuff.Id(node0) - id1 = tempVBuff.Id(node1) - id2 = tempVBuff.Id(node2) - id3 = tempVBuff.Id(node3) - id4 = tempVBuff.Id(node4) - id5 = tempVBuff.Id(node5) - id6 = tempVBuff.Id(node6) - id7 = tempVBuff.Id(node7) - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id0+1, float32(node0.X), float32(node0.Y), float32(node0.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id1+1, float32(node1.X), float32(node1.Y), float32(node1.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id2+1, float32(node2.X), float32(node2.Y), float32(node2.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id3+1, float32(node3.X), float32(node3.Y), float32(node3.Z))) - if err != nil { - return err + nodes = m.feVertices(l, i) + for n := 0; n < 8; n++ { + ids[n] = tempVBuff.Id(nodes[n]) } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id4+1, float32(node4.X), float32(node4.Y), float32(node4.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id5+1, float32(node5.X), float32(node5.Y), float32(node5.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id6+1, float32(node6.X), float32(node6.Y), float32(node6.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id7+1, float32(node7.X), float32(node7.Y), float32(node7.Z))) - if err != nil { - return err + + // Write the node IDs. + for n := 0; n < 8; n++ { + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) + if err != nil { + return err + } } } } @@ -228,17 +203,13 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { var eleID uint32 for l := layerStart; l < layerEnd; l++ { for i := 0; i < m.feCountOnLayer(l); i++ { - node0, node1, node2, node3, node4, node5, node6, node7 = m.feVertices(l, i) - id0 = tempVBuff.Id(node0) - id1 = tempVBuff.Id(node1) - id2 = tempVBuff.Id(node2) - id3 = tempVBuff.Id(node3) - id4 = tempVBuff.Id(node4) - id5 = tempVBuff.Id(node5) - id6 = tempVBuff.Id(node6) - id7 = tempVBuff.Id(node7) + nodes = m.feVertices(l, i) + for n := 0; n < 8; n++ { + ids[n] = tempVBuff.Id(nodes[n]) + } + // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, id0+1, id1+1, id2+1, id3+1, id4+1, id5+1, id6+1, id7+1)) + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) if err != nil { return err } From 84c981472194bc8d1901d5add5c5e1ade8933bfb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 14:35:00 +0330 Subject: [PATCH 131/775] Rename to be consistent --- render/hex8.go | 6 +++--- render/tet4.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/render/hex8.go b/render/hex8.go index 26601a1d9..65e704972 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -232,9 +232,9 @@ func writeHex8(wg *sync.WaitGroup, hex8s *[]Hex8) chan<- []*Hex8 { go func() { defer wg.Done() // read finite elements from the channel and handle them - for ts := range c { - for _, t := range ts { - *hex8s = append(*hex8s, *t) + for fes := range c { + for _, fe := range fes { + *hex8s = append(*hex8s, *fe) } } }() diff --git a/render/tet4.go b/render/tet4.go index 6d258722a..cd81a446b 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -232,9 +232,9 @@ func writeTet4(wg *sync.WaitGroup, tet4s *[]Tet4) chan<- []*Tet4 { go func() { defer wg.Done() // read finite elements from the channel and handle them - for ts := range c { - for _, t := range ts { - *tet4s = append(*tet4s, *t) + for fes := range c { + for _, fe := range fes { + *tet4s = append(*tet4s, *fe) } } }() From 5d27b82c613a5945360a97fbd4479609f4783f01 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 14:37:25 +0330 Subject: [PATCH 132/775] Comment: modify --- render/hex8.go | 6 +++--- render/tet4.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/render/hex8.go b/render/hex8.go index 65e704972..eac8c06bd 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -222,10 +222,10 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { //----------------------------------------------------------------------------- -// writeHex8 writes a stream of finite elements, in the shape of 8-node hexahedra, to an array. +// writeHex8 writes a stream of finite elements to an array. func writeHex8(wg *sync.WaitGroup, hex8s *[]Hex8) chan<- []*Hex8 { - // External code writes tetrahedra to this channel. - // This goroutine reads the channel and stores tetrahedra. + // External code writes to this channel. + // This goroutine reads the channel and stores finite elements. c := make(chan []*Hex8) wg.Add(1) diff --git a/render/tet4.go b/render/tet4.go index cd81a446b..a4de86518 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -222,10 +222,10 @@ func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { //----------------------------------------------------------------------------- -// writeTet4 writes a stream of finite elements, in the shape of 4-node tetrahedra, to an array. +// writeTet4 writes a stream of finite elements to an array. func writeTet4(wg *sync.WaitGroup, tet4s *[]Tet4) chan<- []*Tet4 { - // External code writes tetrahedra to this channel. - // This goroutine reads the channel and stores tetrahedra. + // External code writes to this channel. + // This goroutine reads the channel and stores finite elements. c := make(chan []*Tet4) wg.Add(1) From 9f83912847ee638ce197d90baee621547d3a0f5d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 14:40:41 +0330 Subject: [PATCH 133/775] Consistent comments --- render/tet4.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/render/tet4.go b/render/tet4.go index a4de86518..07dcbf25f 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -20,14 +20,14 @@ type Tet4 struct { // The layer to which tetrahedron belongs. Layers are along Z axis. // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store layer along Z axis. // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. - // Sampling/marching algorithm is expected to generate finite elements along the Z axis. + // Sampling/marching algorithm is expected to return the layer to which a finite element belongs. layer int } //----------------------------------------------------------------------------- -// A mesh of tetrahedra with 4 nodes. -// A sophisticated data structure for mesh is required to store tetrahedra. +// A mesh of 4-node tetrahedra. +// A sophisticated data structure for mesh is required. // The repeated nodes would be removed. // The element connectivity would be created with unique nodes. type MeshTet4 struct { From 193d7e884094f3931a45ca6a4bf7b58ed15fea6b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 5 Mar 2023 14:47:11 +0330 Subject: [PATCH 134/775] Fix unused parameter --- examples/finite_elements/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 2b1f9a54e..f41bdbdbe 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -25,7 +25,7 @@ import ( // Written file can be used by ABAQUS or CalculiX. func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := render.NewMeshTet4(s, render.NewMarchingTet4Uniform(200)) + m, _ := render.NewMeshTet4(s, render.NewMarchingTet4Uniform(resolution)) // Write mesh to file. err := m.WriteInp(pth) @@ -48,7 +48,7 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Written file can be used by ABAQUS or CalculiX. func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := render.NewMeshHex8(s, render.NewMarchingHex8Uniform(200)) + m, _ := render.NewMeshHex8(s, render.NewMarchingHex8Uniform(resolution)) // Write mesh to file. err := m.WriteInp(pth) From f453ddbcb6e5067bf1571ace012529ddc7abbdb2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 11:13:41 +0330 Subject: [PATCH 135/775] Example README --- examples/finite_elements/README.md | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 examples/finite_elements/README.md diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md new file mode 100644 index 000000000..77f6a90a7 --- /dev/null +++ b/examples/finite_elements/README.md @@ -0,0 +1,38 @@ +# CCX and CGX + +The example results can be consumed by ABAQUS or CalculiX. + +CalculiX and CalculiX GraphiX binaries are available for different platforms, like Linux distributions. + +openSUSE has [CCX](https://software.opensuse.org/package/ccx) package and also [CGX](https://software.opensuse.org/package/cgx) one. + +To install CCX and CGX on openSUSE Leap 15.4 you can run as root: + +```bash +zypper addrepo https://download.opensuse.org/repositories/science/15.4/science.repo +zypper refresh +zypper install ccx +zypper install cgx +``` + +# Visualize `inp` file + +To visualize the `inp` file by CalculiX GraphiX: + +```bash +cgx -c teapot-hex8.inp +``` + +# Analyze `inp` file + +To run the `inp` files by FEA engines like CalculiX: + +```bash +ccx -i teapot-hex8 +``` + +The above `-i` flag expects a `teapot-hex8.inp` file. The above command creates `frd` files which can be viewed by CalculiX GraphiX: + +```bash +cgx teapot-hex8.frd +``` From a57ce9f30f4f3b56d4d422b400df808dc7314fc2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 11:23:54 +0330 Subject: [PATCH 136/775] Modify README --- examples/finite_elements/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 77f6a90a7..69b656e65 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -31,8 +31,16 @@ To run the `inp` files by FEA engines like CalculiX: ccx -i teapot-hex8 ``` -The above `-i` flag expects a `teapot-hex8.inp` file. The above command creates `frd` files which can be viewed by CalculiX GraphiX: +The above `-i` flag expects a `teapot-hex8.inp` file. + +The above command creates `frd` files containing the results. They can be viewed by CalculiX GraphiX: ```bash cgx teapot-hex8.frd ``` + +The boundary conditions and loads used in the calculation will be available together with the results if you run: + +```bash +cgx teapot-hex8.frd teapot-hex8.inp +``` From 2ee73956bee97f8b9e260d6a39b809fd6b9706de Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 11:52:07 +0330 Subject: [PATCH 137/775] README modification --- examples/finite_elements/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 69b656e65..151f3f0bd 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -4,6 +4,8 @@ The example results can be consumed by ABAQUS or CalculiX. CalculiX and CalculiX GraphiX binaries are available for different platforms, like Linux distributions. +## openSUSE + openSUSE has [CCX](https://software.opensuse.org/package/ccx) package and also [CGX](https://software.opensuse.org/package/cgx) one. To install CCX and CGX on openSUSE Leap 15.4 you can run as root: From 6abdb59782a64989858c9749446d292f3fd913a7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 12:26:29 +0330 Subject: [PATCH 138/775] Acceleration load: gravity in positive z-direction --- render/hex8.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/render/hex8.go b/render/hex8.go index eac8c06bd..453e89661 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -217,6 +217,26 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { } } + // Write loads. + + _, err = f.WriteString("*DLOAD\n") + if err != nil { + return err + } + + // Assign gravity loading in the "positive" z-direction with magnitude 9810 to all elements. + // + // SLA 3D printing is done upside-down. 3D model is hanging from the print floor. + // That's why gravity is in "positive" z-direction. + // Here ”gravity” really stands for any acceleration vector. + // + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + _, err = f.WriteString("*Eall,GRAV,9810.,0.,0.,+1.\n") + if err != nil { + return err + } + return nil } From ddee508c3ef67cce759cc91fe98f0261b8c1a886 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 12:51:56 +0330 Subject: [PATCH 139/775] Comment --- render/hex8.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/hex8.go b/render/hex8.go index 453e89661..c8bd060ca 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -217,7 +217,7 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { } } - // Write loads. + // Write distributed loads. _, err = f.WriteString("*DLOAD\n") if err != nil { From 1b4b96806963dd23044c8409a7d6f6966b6cee2d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 14:46:42 +0330 Subject: [PATCH 140/775] Material & static analysis --- render/hex8.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/render/hex8.go b/render/hex8.go index c8bd060ca..f81abb417 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -217,6 +217,37 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { } } + // Define material + // TODO: Correct resin specifications. + + _, err = f.WriteString("*MATERIAL, name=resin\n") + if err != nil { + return err + } + + _, err = f.WriteString("*ELASTIC,TYPE=ISO\n210000,0.333333333,0\n") + if err != nil { + return err + } + + _, err = f.WriteString("*DENSITY\n7.8E-9\n") + if err != nil { + return err + } + + // Assign material to all elements + _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=Eall\n") + if err != nil { + return err + } + + // Write analysis + + _, err = f.WriteString("*STEP\n*STATIC\n") + if err != nil { + return err + } + // Write distributed loads. _, err = f.WriteString("*DLOAD\n") @@ -237,6 +268,37 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { return err } + // Pick element results. + + _, err = f.WriteString("*EL FILE\n") + if err != nil { + return err + } + + _, err = f.WriteString("S\n") + if err != nil { + return err + } + + // Pick node results. + + _, err = f.WriteString("*NODE FILE\n") + if err != nil { + return err + } + + _, err = f.WriteString("U\n") + if err != nil { + return err + } + + // Conclude. + + _, err = f.WriteString("*END STEP\n") + if err != nil { + return err + } + return nil } From ba3edbfcbba4a845ff70c4e8178133ad885c7e51 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 15:04:31 +0330 Subject: [PATCH 141/775] Prescribe boundary conditions --- examples/finite_elements/main.go | 2 +- render/hex8.go | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f41bdbdbe..1cc9c6c13 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -57,7 +57,7 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { } // Write just some layers of mesh to a file. - err = m.WriteInpLayers("some-layers-of-"+pth, 0, 32) + err = m.WriteInpLayers("some-layers-of-"+pth, 0, 32, []int{0, 1, 2}) if err != nil { return err } diff --git a/render/hex8.go b/render/hex8.go index f81abb417..b132eacd9 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -130,13 +130,13 @@ func (m *MeshHex8) feVertices(l, i int) [8]v3.Vec { // Write mesh to ABAQUS or CalculiX `inp` file. func (m *MeshHex8) WriteInp(path string) error { - return m.WriteInpLayers(path, 0, m.layerCount()) + return m.WriteInpLayers(path, 0, m.layerCount(), []int{0}) } // Write specific layers of mesh to ABAQUS or CalculiX `inp` file. // Result would include start layer. // Result would exclude end layer. -func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { +func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int, layersFixed []int) error { if 0 <= layerStart && layerStart < layerEnd && layerEnd <= m.layerCount() { // Good. } else { @@ -217,6 +217,31 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int) error { } } + // Fix the degrees of freedom one through three for all nodes on specific layers. + + _, err = f.WriteString("*BOUNDARY\n") + if err != nil { + return err + } + + for l := range layersFixed { + for i := 0; i < m.feCountOnLayer(l); i++ { + nodes = m.feVertices(l, i) + for n := 0; n < 8; n++ { + ids[n] = tempVBuff.Id(nodes[n]) + } + + // Write the node IDs. + for n := 0; n < 8; n++ { + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) + if err != nil { + return err + } + } + } + } + // Define material // TODO: Correct resin specifications. From 243a37251b2fcc50bf002f77d38fa5f4c2d7181b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 15:35:53 +0330 Subject: [PATCH 142/775] Try to fix warning: *WARNING in calinput. Card image cannot be inter preted: *WARNING reading the input file. Card image: *EALL,GRAV,9810.,0.,0.,+1. --- render/hex8.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/hex8.go b/render/hex8.go index b132eacd9..dc461f63d 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -288,7 +288,7 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int, layersF // // Refer to CalculiX solver documentation: // http://www.dhondt.de/ccx_2.20.pdf - _, err = f.WriteString("*Eall,GRAV,9810.,0.,0.,+1.\n") + _, err = f.WriteString("*Eall,GRAV,9810.,0.,0.,1.\n") if err != nil { return err } From c15420daf2c782df07981d30bedd20ef804c1c77 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 15:52:23 +0330 Subject: [PATCH 143/775] Fix bug --- examples/finite_elements/main.go | 4 ++-- render/hex8.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 1cc9c6c13..d977d3122 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -79,12 +79,12 @@ func main() { log.Fatalf("error: %s", err) } - err = tet4FiniteElements(teapotSdf, 200, "teapot-tet4.inp") + err = tet4FiniteElements(teapotSdf, 100, "teapot-tet4.inp") if err != nil { log.Fatalf("error: %s", err) } - err = hex8FiniteElements(teapotSdf, 200, "teapot-hex8.inp") + err = hex8FiniteElements(teapotSdf, 100, "teapot-hex8.inp") if err != nil { log.Fatalf("error: %s", err) } diff --git a/render/hex8.go b/render/hex8.go index dc461f63d..dde7ca5d3 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -288,7 +288,7 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int, layersF // // Refer to CalculiX solver documentation: // http://www.dhondt.de/ccx_2.20.pdf - _, err = f.WriteString("*Eall,GRAV,9810.,0.,0.,1.\n") + _, err = f.WriteString("Eall,GRAV,9810.,0.,0.,1.\n") if err != nil { return err } From c49e8ee7c17869a6709484ba7785d235b112d193 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 6 Mar 2023 16:34:10 +0330 Subject: [PATCH 144/775] Pass parameter --- examples/finite_elements/main.go | 2 +- render/hex8.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index d977d3122..0b866ed38 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -51,7 +51,7 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { m, _ := render.NewMeshHex8(s, render.NewMarchingHex8Uniform(resolution)) // Write mesh to file. - err := m.WriteInp(pth) + err := m.WriteInp(pth, []int{0, 1, 2}) if err != nil { return err } diff --git a/render/hex8.go b/render/hex8.go index dde7ca5d3..c0da2ca67 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -129,8 +129,8 @@ func (m *MeshHex8) feVertices(l, i int) [8]v3.Vec { } // Write mesh to ABAQUS or CalculiX `inp` file. -func (m *MeshHex8) WriteInp(path string) error { - return m.WriteInpLayers(path, 0, m.layerCount(), []int{0}) +func (m *MeshHex8) WriteInp(path string, layersFixed []int) error { + return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed) } // Write specific layers of mesh to ABAQUS or CalculiX `inp` file. From 10dfa4fc7892c16aacf1373de0c9558de9942c93 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 7 Mar 2023 15:19:47 +0330 Subject: [PATCH 145/775] Comment: units of measurement --- render/hex8.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/render/hex8.go b/render/hex8.go index c0da2ca67..3a2e2a1a7 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -242,7 +242,10 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int, layersF } } - // Define material + // Define material. + // Units of measurement are mm,N,s,K. + // Refer to: + // https://engineering.stackexchange.com/q/54454/15178 // TODO: Correct resin specifications. _, err = f.WriteString("*MATERIAL, name=resin\n") From 09d11b1e55d8af02dc295ae0c47198671c53713d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 7 Mar 2023 15:32:34 +0330 Subject: [PATCH 146/775] Pass material properties as arguments --- examples/finite_elements/main.go | 4 ++-- render/hex8.go | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 0b866ed38..a4c55a0ab 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -51,13 +51,13 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { m, _ := render.NewMeshHex8(s, render.NewMarchingHex8Uniform(resolution)) // Write mesh to file. - err := m.WriteInp(pth, []int{0, 1, 2}) + err := m.WriteInp(pth, []int{0, 1, 2}, 7.8e-9, 210000, 0.333333333) if err != nil { return err } // Write just some layers of mesh to a file. - err = m.WriteInpLayers("some-layers-of-"+pth, 0, 32, []int{0, 1, 2}) + err = m.WriteInpLayers("some-layers-of-"+pth, 0, 32, []int{0, 1, 2}, 7.8e-9, 210000, 0.333333333) if err != nil { return err } diff --git a/render/hex8.go b/render/hex8.go index 3a2e2a1a7..f4eb3b3b3 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -129,14 +129,31 @@ func (m *MeshHex8) feVertices(l, i int) [8]v3.Vec { } // Write mesh to ABAQUS or CalculiX `inp` file. -func (m *MeshHex8) WriteInp(path string, layersFixed []int) error { - return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed) +// Units of measurement are mm,N,s,K. +// Refer to https://engineering.stackexchange.com/q/54454/15178 +func (m *MeshHex8) WriteInp( + path string, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) } // Write specific layers of mesh to ABAQUS or CalculiX `inp` file. // Result would include start layer. // Result would exclude end layer. -func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int, layersFixed []int) error { +// Units of measurement are mm,N,s,K. +// Refer to https://engineering.stackexchange.com/q/54454/15178 +func (m *MeshHex8) WriteInpLayers( + path string, + layerStart, layerEnd int, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { if 0 <= layerStart && layerStart < layerEnd && layerEnd <= m.layerCount() { // Good. } else { @@ -253,12 +270,12 @@ func (m *MeshHex8) WriteInpLayers(path string, layerStart, layerEnd int, layersF return err } - _, err = f.WriteString("*ELASTIC,TYPE=ISO\n210000,0.333333333,0\n") + _, err = f.WriteString(fmt.Sprintf("*ELASTIC,TYPE=ISO\n%f,%f,0\n", youngModulus, poissonRatio)) if err != nil { return err } - _, err = f.WriteString("*DENSITY\n7.8E-9\n") + _, err = f.WriteString(fmt.Sprintf("*DENSITY\n%f\n", massDensity)) if err != nil { return err } From 1a67bedf1411be3ae48a5b47b2528ffbc32de91d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 10:45:57 +0330 Subject: [PATCH 147/775] Fix: scientific notation was printed as zero --- render/hex8.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/hex8.go b/render/hex8.go index f4eb3b3b3..ab6e3744f 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -270,12 +270,12 @@ func (m *MeshHex8) WriteInpLayers( return err } - _, err = f.WriteString(fmt.Sprintf("*ELASTIC,TYPE=ISO\n%f,%f,0\n", youngModulus, poissonRatio)) + _, err = f.WriteString(fmt.Sprintf("*ELASTIC,TYPE=ISO\n%e,%e,0\n", youngModulus, poissonRatio)) if err != nil { return err } - _, err = f.WriteString(fmt.Sprintf("*DENSITY\n%f\n", massDensity)) + _, err = f.WriteString(fmt.Sprintf("*DENSITY\n%e\n", massDensity)) if err != nil { return err } From f497608edeb04ee93e9a063daeda84e0654e6d53 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 11:04:58 +0330 Subject: [PATCH 148/775] Simplify example --- examples/finite_elements/main.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index a4c55a0ab..86a834645 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -27,14 +27,11 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := render.NewMeshTet4(s, render.NewMarchingTet4Uniform(resolution)) - // Write mesh to file. - err := m.WriteInp(pth) - if err != nil { - return err - } + lyrStart := 0 + lyrEnd := 20 // Write just some layers of mesh to a file. - err = m.WriteInpLayers("some-layers-of-"+pth, 0, 32) + err := m.WriteInpLayers(pth, lyrStart, lyrEnd) if err != nil { return err } @@ -50,14 +47,11 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := render.NewMeshHex8(s, render.NewMarchingHex8Uniform(resolution)) - // Write mesh to file. - err := m.WriteInp(pth, []int{0, 1, 2}, 7.8e-9, 210000, 0.333333333) - if err != nil { - return err - } + lyrStart := 0 + lyrEnd := 20 // Write just some layers of mesh to a file. - err = m.WriteInpLayers("some-layers-of-"+pth, 0, 32, []int{0, 1, 2}, 7.8e-9, 210000, 0.333333333) + err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 7.8e-9, 210000, 0.333333333) if err != nil { return err } @@ -79,12 +73,12 @@ func main() { log.Fatalf("error: %s", err) } - err = tet4FiniteElements(teapotSdf, 100, "teapot-tet4.inp") + err = tet4FiniteElements(teapotSdf, 80, "teapot-tet4.inp") if err != nil { log.Fatalf("error: %s", err) } - err = hex8FiniteElements(teapotSdf, 100, "teapot-hex8.inp") + err = hex8FiniteElements(teapotSdf, 80, "teapot-hex8.inp") if err != nil { log.Fatalf("error: %s", err) } From e97322e2da234be9a798e25065132698c1a2fa77 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 11:44:44 +0330 Subject: [PATCH 149/775] Sample mechanical properties based on SLA resins --- examples/finite_elements/main.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 86a834645..87537dfc4 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -51,7 +51,15 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { lyrEnd := 20 // Write just some layers of mesh to a file. - err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 7.8e-9, 210000, 0.333333333) + // + // Units are mm,N,sec. + // Force per area = N/mm2 or MPa + // Mass density = Ns2/mm4 + // Refer to the "Units" chapter of: + // http://www.dhondt.de/ccx_2.20.pdf + // + // Mechanical properties are based on typical SLA resins. + err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1120e-12, 1200, 0.3) if err != nil { return err } From 1fe2e0b61a3a8218c5c2f142854f33adb7170081 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 11:58:49 +0330 Subject: [PATCH 150/775] Change example mechanical specs --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 87537dfc4..37903a91d 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -59,7 +59,7 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // http://www.dhondt.de/ccx_2.20.pdf // // Mechanical properties are based on typical SLA resins. - err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1120e-12, 1200, 0.3) + err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) if err != nil { return err } From 9f717cecbff6f9779697bce5d4185d1b82b104bf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 12:38:47 +0330 Subject: [PATCH 151/775] Write nodes & elements to separate files: To avoid cluttering the `inp` file. --- render/hex8.go | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/render/hex8.go b/render/hex8.go index ab6e3744f..c209312e1 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -185,6 +185,20 @@ func (m *MeshHex8) WriteInpLayers( return err } + // Write to a separate file to avoid cluttering the `inp` file. + pathNodes := path + ".nodes" + fNodes, err := os.Create(pathNodes) + if err != nil { + return err + } + defer fNodes.Close() + + // Write to a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", pathNodes)) + if err != nil { + return err + } + // To write only required nodes to the file. tempVBuff := buffer.NewVB() defer tempVBuff.DestroyHashTable() @@ -202,7 +216,7 @@ func (m *MeshHex8) WriteInpLayers( // Write the node IDs. for n := 0; n < 8; n++ { // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) + _, err = fNodes.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) if err != nil { return err } @@ -217,6 +231,20 @@ func (m *MeshHex8) WriteInpLayers( return err } + // Write to a separate file to avoid cluttering the `inp` file. + pathEls := path + ".elements" + fEls, err := os.Create(pathEls) + if err != nil { + return err + } + defer fEls.Close() + + // Write to a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", pathEls)) + if err != nil { + return err + } + var eleID uint32 for l := layerStart; l < layerEnd; l++ { for i := 0; i < m.feCountOnLayer(l); i++ { @@ -226,7 +254,7 @@ func (m *MeshHex8) WriteInpLayers( } // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) + _, err = fEls.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) if err != nil { return err } From 2628d46399706ea783c9d1c9f1a1d2caa0c21652 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 13:20:01 +0330 Subject: [PATCH 152/775] Write boundary conditions to a separate file: To avoid cluttering the `inp` file. --- render/hex8.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/render/hex8.go b/render/hex8.go index c209312e1..b6f3b0908 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -269,6 +269,20 @@ func (m *MeshHex8) WriteInpLayers( return err } + // Write to a separate file to avoid cluttering the `inp` file. + pathBou := path + ".boundary" + fBou, err := os.Create(pathBou) + if err != nil { + return err + } + defer fBou.Close() + + // Write to a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", pathBou)) + if err != nil { + return err + } + for l := range layersFixed { for i := 0; i < m.feCountOnLayer(l); i++ { nodes = m.feVertices(l, i) @@ -279,7 +293,7 @@ func (m *MeshHex8) WriteInpLayers( // Write the node IDs. for n := 0; n < 8; n++ { // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) + _, err = fBou.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) if err != nil { return err } From 0da1aeb71272db8314d706967a74e19da0c7465c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 13:22:45 +0330 Subject: [PATCH 153/775] TODO --- examples/finite_elements/main.go | 2 ++ render/hex8.go | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 37903a91d..d76e95b88 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -59,6 +59,8 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // http://www.dhondt.de/ccx_2.20.pdf // // Mechanical properties are based on typical SLA resins. + // + // TODO: Correct resin specifications. err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) if err != nil { return err diff --git a/render/hex8.go b/render/hex8.go index b6f3b0908..a4bc165fd 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -305,7 +305,6 @@ func (m *MeshHex8) WriteInpLayers( // Units of measurement are mm,N,s,K. // Refer to: // https://engineering.stackexchange.com/q/54454/15178 - // TODO: Correct resin specifications. _, err = f.WriteString("*MATERIAL, name=resin\n") if err != nil { From aa62541857386172af74945f891de831adc019f6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 15:44:53 +0330 Subject: [PATCH 154/775] New type & funcs to write `inp` for all FE types --- render/inp.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 render/inp.go diff --git a/render/inp.go b/render/inp.go new file mode 100644 index 000000000..6e619e65f --- /dev/null +++ b/render/inp.go @@ -0,0 +1,37 @@ +package render + +import "github.com/deadsy/sdfx/render/buffer" + +type FEType int + +const ( + FETet4 FEType = iota + 1 + FEHex8 + FEHex20 +) + +// To write different types of finite elements as ABAQUS or CalculiX `inp` file. +type Inp struct { + // To be able to write to `inp` for all types of FE. + ElType FEType + // To write only required nodes to `inp` file. + TempVBuff *buffer.VB + // Output `inp` file path. + Path string +} + +func NewInp(elType FEType, path string) *Inp { + return &Inp{ + ElType: elType, + TempVBuff: buffer.NewVB(), + Path: path, + } +} + +func (inp *Inp) WriteTet4(m *MeshTet4) error { + return nil +} + +func (inp *Inp) WriteHex8(m *MeshHex8) error { + return nil +} From 2b57c89ca68b77c2bdb093ae80f84b1da67e5b70 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 15:47:36 +0330 Subject: [PATCH 155/775] Simplify --- render/inp.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/render/inp.go b/render/inp.go index 6e619e65f..ebb8ace53 100644 --- a/render/inp.go +++ b/render/inp.go @@ -2,27 +2,16 @@ package render import "github.com/deadsy/sdfx/render/buffer" -type FEType int - -const ( - FETet4 FEType = iota + 1 - FEHex8 - FEHex20 -) - // To write different types of finite elements as ABAQUS or CalculiX `inp` file. type Inp struct { - // To be able to write to `inp` for all types of FE. - ElType FEType // To write only required nodes to `inp` file. TempVBuff *buffer.VB // Output `inp` file path. Path string } -func NewInp(elType FEType, path string) *Inp { +func NewInp(path string) *Inp { return &Inp{ - ElType: elType, TempVBuff: buffer.NewVB(), Path: path, } From d526ce09f2ad8bf69d9cc602b373e8954ca963c1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 15:55:53 +0330 Subject: [PATCH 156/775] New func to write header --- render/inp.go | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/render/inp.go b/render/inp.go index ebb8ace53..5fc8efc70 100644 --- a/render/inp.go +++ b/render/inp.go @@ -1,26 +1,58 @@ package render -import "github.com/deadsy/sdfx/render/buffer" +import ( + "fmt" + + "github.com/deadsy/sdfx/render/buffer" +) // To write different types of finite elements as ABAQUS or CalculiX `inp` file. type Inp struct { - // To write only required nodes to `inp` file. - TempVBuff *buffer.VB // Output `inp` file path. Path string + // Output `inp` file would include start layer. + LayerStart int + // Output `inp` file would exclude end layer. + LayerEnd int + // To write only required nodes to `inp` file. + TempVBuff *buffer.VB + // Mechanical properties of 3D print resin. + MassDensity float32 + YoungModulus float32 + PoissonRatio float32 } -func NewInp(path string) *Inp { +func NewInp(path string, layerStart, layerEnd int, massDensity float32, youngModulus float32, poissonRatio float32) *Inp { return &Inp{ - TempVBuff: buffer.NewVB(), - Path: path, + Path: path, + LayerStart: layerStart, + LayerEnd: layerEnd, + TempVBuff: buffer.NewVB(), + MassDensity: massDensity, + YoungModulus: youngModulus, + PoissonRatio: poissonRatio, } } func (inp *Inp) WriteTet4(m *MeshTet4) error { + inp.writeHeader() return nil } func (inp *Inp) WriteHex8(m *MeshHex8) error { + inp.writeHeader() return nil } + +func (inp *Inp) WriteHex20() error { + inp.writeHeader() + return nil +} + +func (inp *Inp) writeHeader() error { + if 0 <= inp.LayerStart && inp.LayerStart < inp.LayerEnd && inp.LayerEnd <= m.layerCount() { + // Good. + } else { + return fmt.Errorf("start or end layer is beyond range") + } +} From 91172354455485da7aa6c77a0d10d19aae670c48 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 15:57:53 +0330 Subject: [PATCH 157/775] New pkg for writing to `inp` file --- render/{ => inp}/inp.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename render/{ => inp}/inp.go (93%) diff --git a/render/inp.go b/render/inp/inp.go similarity index 93% rename from render/inp.go rename to render/inp/inp.go index 5fc8efc70..e5700bfb0 100644 --- a/render/inp.go +++ b/render/inp/inp.go @@ -1,4 +1,5 @@ -package render +// To write different types of finite elements as ABAQUS or CalculiX `inp` file. +package inp import ( "fmt" From b4fa5bc63a83a9c8878e160d7739906c251b3138 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 9 Mar 2023 16:00:28 +0330 Subject: [PATCH 158/775] Revert "New pkg for writing to `inp` file" This reverts commit 91172354455485da7aa6c77a0d10d19aae670c48. --- render/{inp => }/inp.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename render/{inp => }/inp.go (93%) diff --git a/render/inp/inp.go b/render/inp.go similarity index 93% rename from render/inp/inp.go rename to render/inp.go index e5700bfb0..5fc8efc70 100644 --- a/render/inp/inp.go +++ b/render/inp.go @@ -1,5 +1,4 @@ -// To write different types of finite elements as ABAQUS or CalculiX `inp` file. -package inp +package render import ( "fmt" From cf870f268c440ef64b6d15958008f67fc18de619 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 12:35:15 +0330 Subject: [PATCH 159/775] Redesign code for finite elements: New pkg and types --- examples/finite_elements/main.go | 7 +- render/{ => finiteelements}/buffer/buffer.go | 0 .../buffer/hex8indexbuffer.go | 0 .../buffer/tet4indexbuffer.go | 0 .../buffer/vertexbuffer.go | 0 render/finiteelements/mesh/hex8.go | 146 +++++++ render/finiteelements/mesh/inp.go | 369 +++++++++++++++++ render/finiteelements/mesh/mesh.go | 3 + render/finiteelements/mesh/tet4.go | 137 +++++++ render/hex8.go | 371 +----------------- render/inp.go | 58 --- render/marchhex8.go | 2 +- render/marchtet4.go | 2 +- render/tet4.go | 209 +--------- 14 files changed, 666 insertions(+), 638 deletions(-) rename render/{ => finiteelements}/buffer/buffer.go (100%) rename render/{ => finiteelements}/buffer/hex8indexbuffer.go (100%) rename render/{ => finiteelements}/buffer/tet4indexbuffer.go (100%) rename render/{ => finiteelements}/buffer/vertexbuffer.go (100%) create mode 100644 render/finiteelements/mesh/hex8.go create mode 100644 render/finiteelements/mesh/inp.go create mode 100644 render/finiteelements/mesh/mesh.go create mode 100644 render/finiteelements/mesh/tet4.go delete mode 100644 render/inp.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index d76e95b88..3d9591015 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -15,6 +15,7 @@ import ( "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" + "github.com/deadsy/sdfx/render/finiteelements/mesh" "github.com/deadsy/sdfx/sdf" ) @@ -25,13 +26,13 @@ import ( // Written file can be used by ABAQUS or CalculiX. func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := render.NewMeshTet4(s, render.NewMarchingTet4Uniform(resolution)) + m, _ := mesh.NewMeshTet4(s, render.NewMarchingTet4Uniform(resolution)) lyrStart := 0 lyrEnd := 20 // Write just some layers of mesh to a file. - err := m.WriteInpLayers(pth, lyrStart, lyrEnd) + err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) if err != nil { return err } @@ -45,7 +46,7 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Written file can be used by ABAQUS or CalculiX. func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := render.NewMeshHex8(s, render.NewMarchingHex8Uniform(resolution)) + m, _ := mesh.NewMeshHex8(s, render.NewMarchingHex8Uniform(resolution)) lyrStart := 0 lyrEnd := 20 diff --git a/render/buffer/buffer.go b/render/finiteelements/buffer/buffer.go similarity index 100% rename from render/buffer/buffer.go rename to render/finiteelements/buffer/buffer.go diff --git a/render/buffer/hex8indexbuffer.go b/render/finiteelements/buffer/hex8indexbuffer.go similarity index 100% rename from render/buffer/hex8indexbuffer.go rename to render/finiteelements/buffer/hex8indexbuffer.go diff --git a/render/buffer/tet4indexbuffer.go b/render/finiteelements/buffer/tet4indexbuffer.go similarity index 100% rename from render/buffer/tet4indexbuffer.go rename to render/finiteelements/buffer/tet4indexbuffer.go diff --git a/render/buffer/vertexbuffer.go b/render/finiteelements/buffer/vertexbuffer.go similarity index 100% rename from render/buffer/vertexbuffer.go rename to render/finiteelements/buffer/vertexbuffer.go diff --git a/render/finiteelements/mesh/hex8.go b/render/finiteelements/mesh/hex8.go new file mode 100644 index 000000000..a39c32f99 --- /dev/null +++ b/render/finiteelements/mesh/hex8.go @@ -0,0 +1,146 @@ +package mesh + +import ( + "github.com/deadsy/sdfx/render" + "github.com/deadsy/sdfx/render/finiteelements/buffer" + "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// A mesh of 8-node hexahedra. +// A sophisticated data structure for mesh is required. +// The repeated nodes would be removed. +// The element connectivity would be created with unique nodes. +type MeshHex8 struct { + // Index buffer. + IBuff *buffer.Hex8IB + // Vertex buffer. + VBuff *buffer.VB +} + +// To get a new mesh and number of its layers along Z-axis. +func NewMeshHex8(s sdf.SDF3, r render.RenderHex8) (*MeshHex8, int) { + fes := render.ToHex8(s, r) + + _, _, layerCountZ := r.LayerCounts(s) + + m := newMeshHex8(layerCountZ) + + // Fill out the mesh with finite elements. + for _, fe := range fes { + nodes := [8]v3.Vec{} + for n := 0; n < 8; n++ { + nodes[n] = fe.V[n] + } + m.addFE(fe.Layer, nodes) + } + + defer m.VBuff.DestroyHashTable() + + return m, layerCountZ +} + +func newMeshHex8(layerCount int) *MeshHex8 { + return &MeshHex8{ + IBuff: buffer.NewHex8IB(layerCount), + VBuff: buffer.NewVB(), + } +} + +func (m *MeshHex8) NodesPerElement() int { + return 8 +} + +// Add a finite element to mesh. +// Layer number and nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (m *MeshHex8) addFE(l int, nodes [8]v3.Vec) { + indices := [8]uint32{} + for n := 0; n < 8; n++ { + indices[n] = m.addVertex(nodes[n]) + } + m.IBuff.AddFE(l, indices) +} + +func (m *MeshHex8) addVertex(vert v3.Vec) uint32 { + return m.VBuff.Id(vert) +} + +func (m *MeshHex8) vertexCount() int { + return m.VBuff.VertexCount() +} + +func (m *MeshHex8) vertex(i uint32) v3.Vec { + return m.VBuff.Vertex(i) +} + +// Number of layers along the Z axis. +func (m *MeshHex8) layerCount() int { + return m.IBuff.LayerCount() +} + +// Number of finite elements on a layer. +func (m *MeshHex8) feCountOnLayer(l int) int { + return m.IBuff.FECountOnLayer(l) +} + +// Number of finite elements for all layers. +func (m *MeshHex8) feCount() int { + return m.IBuff.FECount() +} + +// Get a finite element. +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *MeshHex8) feIndicies(l, i int) [8]uint32 { + return m.IBuff.FEIndicies(l, i) +} + +// Get a finite element. +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *MeshHex8) feVertices(l, i int) []v3.Vec { + indices := m.IBuff.FEIndicies(l, i) + vertices := make([]v3.Vec, 8) + for n := 0; n < 8; n++ { + vertices[n] = m.VBuff.Vertex(indices[n]) + } + return vertices +} + +// Write mesh to ABAQUS or CalculiX `inp` file. +// Units of measurement are mm,N,s,K. +// Refer to https://engineering.stackexchange.com/q/54454/15178 +func (m *MeshHex8) WriteInp( + path string, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) +} + +// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +// Result would include start layer. +// Result would exclude end layer. +// Units of measurement are mm,N,s,K. +// Refer to https://engineering.stackexchange.com/q/54454/15178 +func (m *MeshHex8) WriteInpLayers( + path string, + layerStart, layerEnd int, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) + return inp.Write() +} + +//----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go new file mode 100644 index 000000000..02ba1f4c0 --- /dev/null +++ b/render/finiteelements/mesh/inp.go @@ -0,0 +1,369 @@ +package mesh + +import ( + "fmt" + "os" + "time" + + "github.com/deadsy/sdfx/render/finiteelements/buffer" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// A dynamic type for meshes of finite elements like MeshTet4, MeshHex8, MeshHex20, ... +type MeshFE interface { + NodesPerElement() int + layerCount() int + feCountOnLayer(l int) int + feVertices(l, i int) []v3.Vec +} + +//----------------------------------------------------------------------------- + +// To write different types of finite elements as ABAQUS or CalculiX `inp` file. +type Inp struct { + // Finite elements mesh. + Mesh MeshFE + // Output `inp` file path. + Path string + // For writing nodes to a separate file. + PathNodes string + // For writing elements to a separate file. + PathEls string + // For writing boundary conditions to a separate file. + PathBou string + // Output `inp` file would include start layer. + LayerStart int + // Output `inp` file would exclude end layer. + LayerEnd int + // Layers fixed to the 3D print floor i.e. bottom layers. + LayersFixed []int + // To write only required nodes to `inp` file. + TempVBuff *buffer.VB + // Mechanical properties of 3D print resin. + MassDensity float32 + YoungModulus float32 + PoissonRatio float32 +} + +func NewInp( + m MeshFE, + path string, + layerStart, layerEnd int, + layersFixed []int, + massDensity float32, youngModulus float32, poissonRatio float32, +) *Inp { + return &Inp{ + Mesh: m, + Path: path, + PathNodes: path + ".nodes", + PathEls: path + ".elements", + PathBou: path + ".boundary", + LayerStart: layerStart, + LayerEnd: layerEnd, + LayersFixed: layersFixed, + TempVBuff: buffer.NewVB(), + MassDensity: massDensity, + YoungModulus: youngModulus, + PoissonRatio: poissonRatio, + } +} + +func (inp *Inp) Write() error { + f, err := os.Create(inp.Path) + if err != nil { + return err + } + defer f.Close() + + err = inp.writeHeader(f) + if err != nil { + return err + } + + // Write nodes. + + _, err = f.WriteString("*NODE\n") + if err != nil { + return err + } + + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathNodes)) + if err != nil { + return err + } + + // Write to a separate file to avoid cluttering the `inp` file. + fNodes, err := os.Create(inp.PathNodes) + if err != nil { + return err + } + defer fNodes.Close() + + // Temp buffer is just to avoid writing repeated nodes into the `inpt` file. + defer inp.TempVBuff.DestroyHashTable() + + err = inp.writeNodes(fNodes) + if err != nil { + return err + } + + // Write elements. + + ElementType := "" + if inp.Mesh.NodesPerElement() == 4 { + ElementType = "C3D4" + } else if inp.Mesh.NodesPerElement() == 8 { + ElementType = "C3D8" + } else if inp.Mesh.NodesPerElement() == 20 { + ElementType = "C3D20R" + } + + _, err = f.WriteString(fmt.Sprintf("*ELEMENT, TYPE=%s, ELSET=Eall\n", ElementType)) + if err != nil { + return err + } + + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathEls)) + if err != nil { + return err + } + + // Write to a separate file to avoid cluttering the `inp` file. + fEls, err := os.Create(inp.PathEls) + if err != nil { + return err + } + defer fEls.Close() + + err = inp.writeElements(fEls) + if err != nil { + return err + } + + // Fix the degrees of freedom one through three for all nodes on specific layers. + + _, err = f.WriteString("*BOUNDARY\n") + if err != nil { + return err + } + + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathBou)) + if err != nil { + return err + } + + // Write to a separate file to avoid cluttering the `inp` file. + fBou, err := os.Create(inp.PathBou) + if err != nil { + return err + } + defer fBou.Close() + + err = inp.WriteBoundary(fBou) + if err != nil { + return err + } + + return inp.writeFooter(f) +} + +func (inp *Inp) writeHeader(f *os.File) error { + if 0 <= inp.LayerStart && inp.LayerStart < inp.LayerEnd && inp.LayerEnd <= inp.Mesh.layerCount() { + // Good. + } else { + return fmt.Errorf("start or end layer is beyond range") + } + + _, err := f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") + if err != nil { + return err + } + + _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") + if err != nil { + return err + } + + return nil +} + +func (inp *Inp) writeNodes(f *os.File) error { + // Declare vars outside loop for efficiency. + var err error + nodes := make([]v3.Vec, 0, inp.Mesh.NodesPerElement()) + ids := make([]uint32, inp.Mesh.NodesPerElement()) + for l := inp.LayerStart; l < inp.LayerEnd; l++ { + for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { + // Get the node IDs. + nodes = inp.Mesh.feVertices(l, i) + for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + ids[n] = inp.TempVBuff.Id(nodes[n]) + } + + // Write the node IDs. + for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) + if err != nil { + return err + } + } + } + } + + return nil +} + +func (inp *Inp) writeElements(f *os.File) error { + // Declare vars outside loop for efficiency. + var err error + nodes := make([]v3.Vec, 0, inp.Mesh.NodesPerElement()) + ids := make([]uint32, inp.Mesh.NodesPerElement()) + var eleID uint32 + for l := inp.LayerStart; l < inp.LayerEnd; l++ { + for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { + nodes = inp.Mesh.feVertices(l, i) + for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + ids[n] = inp.TempVBuff.Id(nodes[n]) + } + + // ID starts from one not zero. + + if inp.Mesh.NodesPerElement() == 4 { + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1)) + } else if inp.Mesh.NodesPerElement() == 8 { + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) + } else if inp.Mesh.NodesPerElement() == 20 { + // TODO. + } + + if err != nil { + return err + } + eleID++ + } + } + + return nil +} + +func (inp *Inp) WriteBoundary(f *os.File) error { + // Declare vars outside loop for efficiency. + var err error + nodes := make([]v3.Vec, 0, inp.Mesh.NodesPerElement()) + ids := make([]uint32, inp.Mesh.NodesPerElement()) + for l := range inp.LayersFixed { + for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { + nodes = inp.Mesh.feVertices(l, i) + for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + ids[n] = inp.TempVBuff.Id(nodes[n]) + } + + // Write the node IDs. + for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) + if err != nil { + return err + } + } + } + } + + return nil +} + +func (inp *Inp) writeFooter(f *os.File) error { + + // Define material. + // Units of measurement are mm,N,s,K. + // Refer to: + // https://engineering.stackexchange.com/q/54454/15178 + // Refer to: + // Units chapter of CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + + _, err := f.WriteString("*MATERIAL, name=resin\n") + if err != nil { + return err + } + + _, err = f.WriteString(fmt.Sprintf("*ELASTIC,TYPE=ISO\n%e,%e,0\n", inp.YoungModulus, inp.PoissonRatio)) + if err != nil { + return err + } + + _, err = f.WriteString(fmt.Sprintf("*DENSITY\n%e\n", inp.MassDensity)) + if err != nil { + return err + } + + // Assign material to all elements + _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=Eall\n") + if err != nil { + return err + } + + // Write analysis + + _, err = f.WriteString("*STEP\n*STATIC\n") + if err != nil { + return err + } + + // Write distributed loads. + + _, err = f.WriteString("*DLOAD\n") + if err != nil { + return err + } + + // Assign gravity loading in the "positive" z-direction with magnitude 9810 to all elements. + // + // SLA 3D printing is done upside-down. 3D model is hanging from the print floor. + // That's why gravity is in "positive" z-direction. + // Here ”gravity” really stands for any acceleration vector. + // + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + _, err = f.WriteString("Eall,GRAV,9810.,0.,0.,1.\n") + if err != nil { + return err + } + + // Pick element results. + + _, err = f.WriteString("*EL FILE\n") + if err != nil { + return err + } + + _, err = f.WriteString("S\n") + if err != nil { + return err + } + + // Pick node results. + + _, err = f.WriteString("*NODE FILE\n") + if err != nil { + return err + } + + _, err = f.WriteString("U\n") + if err != nil { + return err + } + + // Conclude. + + _, err = f.WriteString("*END STEP\n") + if err != nil { + return err + } + + return nil +} diff --git a/render/finiteelements/mesh/mesh.go b/render/finiteelements/mesh/mesh.go new file mode 100644 index 000000000..2d01613c8 --- /dev/null +++ b/render/finiteelements/mesh/mesh.go @@ -0,0 +1,3 @@ +// Provide convenient types & functions for meshes consisting of finite elements. +// Like 4-node tetrahedra, 8-node and 20-node hexahedra. +package mesh diff --git a/render/finiteelements/mesh/tet4.go b/render/finiteelements/mesh/tet4.go new file mode 100644 index 000000000..0e9bc4173 --- /dev/null +++ b/render/finiteelements/mesh/tet4.go @@ -0,0 +1,137 @@ +package mesh + +import ( + "github.com/deadsy/sdfx/render" + "github.com/deadsy/sdfx/render/finiteelements/buffer" + "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// A mesh of 4-node tetrahedra. +// A sophisticated data structure for mesh is required. +// The repeated nodes would be removed. +// The element connectivity would be created with unique nodes. +type MeshTet4 struct { + // Index buffer. + IBuff *buffer.Tet4IB + // Vertex buffer. + VBuff *buffer.VB +} + +// To get a new mesh and number of its layers along Z-axis. +func NewMeshTet4(s sdf.SDF3, r render.RenderTet4) (*MeshTet4, int) { + fes := render.ToTet4(s, r) + + _, _, layerCountZ := r.LayerCounts(s) + + m := newMeshTet4(layerCountZ) + + // Fill out the mesh with finite elements. + for _, fe := range fes { + m.addFE(fe.Layer, fe.V[0], fe.V[1], fe.V[2], fe.V[3]) + } + + defer m.VBuff.DestroyHashTable() + + return m, layerCountZ +} + +func newMeshTet4(layerCount int) *MeshTet4 { + return &MeshTet4{ + IBuff: buffer.NewTet4IB(layerCount), + VBuff: buffer.NewVB(), + } +} + +func (m *MeshTet4) NodesPerElement() int { + return 4 +} + +// Add a finite element. +// Layer number and nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (m *MeshTet4) addFE(l int, a, b, c, d v3.Vec) { + m.IBuff.AddTet4(l, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) +} + +func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { + return m.VBuff.Id(vert) +} + +func (m *MeshTet4) vertexCount() int { + return m.VBuff.VertexCount() +} + +func (m *MeshTet4) vertex(i uint32) v3.Vec { + return m.VBuff.Vertex(i) +} + +// Number of layers along the Z axis. +func (m *MeshTet4) layerCount() int { + return m.IBuff.LayerCount() +} + +// Number of tetrahedra on a layer. +func (m *MeshTet4) feCountOnLayer(l int) int { + return m.IBuff.FECountOnLayer(l) +} + +// Number of tetrahedra for all layers. +func (m *MeshTet4) feCount() int { + return m.IBuff.FECount() +} + +// Get a finite element. +// Layer number is input. +// Tetrahedron index on layer is input. +// Tetrahedron index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *MeshTet4) feIndicies(l, i int) (uint32, uint32, uint32, uint32) { + return m.IBuff.FEIndicies(l, i) +} + +// Get a finite element. +// Layer number is input. +// Tetrahedron index on layer is input. +// Tetrahedron index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *MeshTet4) feVertices(l, i int) []v3.Vec { + idx0, idx1, idx2, idx3 := m.IBuff.FEIndicies(l, i) + vertices := make([]v3.Vec, 4) + + vertices[0] = m.VBuff.Vertex(idx0) + vertices[1] = m.VBuff.Vertex(idx1) + vertices[2] = m.VBuff.Vertex(idx2) + vertices[3] = m.VBuff.Vertex(idx3) + + return vertices +} + +// Write mesh to ABAQUS or CalculiX `inp` file. +func (m *MeshTet4) WriteInp( + path string, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) +} + +// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +// Result would include start layer. +// Result would exclude end layer. +func (m *MeshTet4) WriteInpLayers( + path string, + layerStart, layerEnd int, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) + return inp.Write() +} + +//----------------------------------------------------------------------------- diff --git a/render/hex8.go b/render/hex8.go index a4bc165fd..964c1744a 100644 --- a/render/hex8.go +++ b/render/hex8.go @@ -1,13 +1,8 @@ package render import ( - "fmt" - "os" "sync" - "time" - "github.com/deadsy/sdfx/render/buffer" - "github.com/deadsy/sdfx/sdf" v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -21,371 +16,7 @@ type Hex8 struct { // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store layer along Z axis. // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. // Sampling/marching algorithm is expected to return the layer to which a finite element belongs. - layer int -} - -//----------------------------------------------------------------------------- - -// A mesh of 8-node hexahedra. -// A sophisticated data structure for mesh is required. -// The repeated nodes would be removed. -// The element connectivity would be created with unique nodes. -type MeshHex8 struct { - // Index buffer. - IBuff *buffer.Hex8IB - // Vertex buffer. - VBuff *buffer.VB -} - -// To get a new mesh and number of its layers along Z-axis. -func NewMeshHex8(s sdf.SDF3, r RenderHex8) (*MeshHex8, int) { - fes := ToHex8(s, r) - - _, _, layerCountZ := r.LayerCounts(s) - - m := newMeshHex8(layerCountZ) - - // Fill out the mesh with finite elements. - for _, fe := range fes { - nodes := [8]v3.Vec{} - for n := 0; n < 8; n++ { - nodes[n] = fe.V[n] - } - m.addFE(fe.layer, nodes) - } - - defer m.VBuff.DestroyHashTable() - - return m, layerCountZ -} - -func newMeshHex8(layerCount int) *MeshHex8 { - return &MeshHex8{ - IBuff: buffer.NewHex8IB(layerCount), - VBuff: buffer.NewVB(), - } -} - -// Add a finite element to mesh. -// Layer number and nodes are input. -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshHex8) addFE(l int, nodes [8]v3.Vec) { - indices := [8]uint32{} - for n := 0; n < 8; n++ { - indices[n] = m.addVertex(nodes[n]) - } - m.IBuff.AddFE(l, indices) -} - -func (m *MeshHex8) addVertex(vert v3.Vec) uint32 { - return m.VBuff.Id(vert) -} - -func (m *MeshHex8) vertexCount() int { - return m.VBuff.VertexCount() -} - -func (m *MeshHex8) vertex(i uint32) v3.Vec { - return m.VBuff.Vertex(i) -} - -// Number of layers along the Z axis. -func (m *MeshHex8) layerCount() int { - return m.IBuff.LayerCount() -} - -// Number of finite elements on a layer. -func (m *MeshHex8) feCountOnLayer(l int) int { - return m.IBuff.FECountOnLayer(l) -} - -// Number of finite elements for all layers. -func (m *MeshHex8) feCount() int { - return m.IBuff.FECount() -} - -// Get a finite element. -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *MeshHex8) feIndicies(l, i int) [8]uint32 { - return m.IBuff.FEIndicies(l, i) -} - -// Get a finite element. -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *MeshHex8) feVertices(l, i int) [8]v3.Vec { - indices := m.IBuff.FEIndicies(l, i) - vertices := [8]v3.Vec{} - for n := 0; n < 8; n++ { - vertices[n] = m.VBuff.Vertex(indices[n]) - } - return vertices -} - -// Write mesh to ABAQUS or CalculiX `inp` file. -// Units of measurement are mm,N,s,K. -// Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *MeshHex8) WriteInp( - path string, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) -} - -// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. -// Result would include start layer. -// Result would exclude end layer. -// Units of measurement are mm,N,s,K. -// Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *MeshHex8) WriteInpLayers( - path string, - layerStart, layerEnd int, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - if 0 <= layerStart && layerStart < layerEnd && layerEnd <= m.layerCount() { - // Good. - } else { - return fmt.Errorf("start or end layer is beyond range") - } - - f, err := os.Create(path) - if err != nil { - return err - } - defer f.Close() - - // Write headers. - - _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") - if err != nil { - return err - } - - _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") - if err != nil { - return err - } - - // Write nodes. - - _, err = f.WriteString("*NODE\n") - if err != nil { - return err - } - - // Write to a separate file to avoid cluttering the `inp` file. - pathNodes := path + ".nodes" - fNodes, err := os.Create(pathNodes) - if err != nil { - return err - } - defer fNodes.Close() - - // Write to a separate file to avoid cluttering the `inp` file. - _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", pathNodes)) - if err != nil { - return err - } - - // To write only required nodes to the file. - tempVBuff := buffer.NewVB() - defer tempVBuff.DestroyHashTable() - - nodes := [8]v3.Vec{} - ids := [8]uint32{} - for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.feCountOnLayer(l); i++ { - // Get the node IDs. - nodes = m.feVertices(l, i) - for n := 0; n < 8; n++ { - ids[n] = tempVBuff.Id(nodes[n]) - } - - // Write the node IDs. - for n := 0; n < 8; n++ { - // ID starts from one not zero. - _, err = fNodes.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) - if err != nil { - return err - } - } - } - } - - // Write elements. - - _, err = f.WriteString("*ELEMENT, TYPE=C3D8, ELSET=Eall\n") - if err != nil { - return err - } - - // Write to a separate file to avoid cluttering the `inp` file. - pathEls := path + ".elements" - fEls, err := os.Create(pathEls) - if err != nil { - return err - } - defer fEls.Close() - - // Write to a separate file to avoid cluttering the `inp` file. - _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", pathEls)) - if err != nil { - return err - } - - var eleID uint32 - for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.feCountOnLayer(l); i++ { - nodes = m.feVertices(l, i) - for n := 0; n < 8; n++ { - ids[n] = tempVBuff.Id(nodes[n]) - } - - // ID starts from one not zero. - _, err = fEls.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) - if err != nil { - return err - } - eleID++ - } - } - - // Fix the degrees of freedom one through three for all nodes on specific layers. - - _, err = f.WriteString("*BOUNDARY\n") - if err != nil { - return err - } - - // Write to a separate file to avoid cluttering the `inp` file. - pathBou := path + ".boundary" - fBou, err := os.Create(pathBou) - if err != nil { - return err - } - defer fBou.Close() - - // Write to a separate file to avoid cluttering the `inp` file. - _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", pathBou)) - if err != nil { - return err - } - - for l := range layersFixed { - for i := 0; i < m.feCountOnLayer(l); i++ { - nodes = m.feVertices(l, i) - for n := 0; n < 8; n++ { - ids[n] = tempVBuff.Id(nodes[n]) - } - - // Write the node IDs. - for n := 0; n < 8; n++ { - // ID starts from one not zero. - _, err = fBou.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) - if err != nil { - return err - } - } - } - } - - // Define material. - // Units of measurement are mm,N,s,K. - // Refer to: - // https://engineering.stackexchange.com/q/54454/15178 - - _, err = f.WriteString("*MATERIAL, name=resin\n") - if err != nil { - return err - } - - _, err = f.WriteString(fmt.Sprintf("*ELASTIC,TYPE=ISO\n%e,%e,0\n", youngModulus, poissonRatio)) - if err != nil { - return err - } - - _, err = f.WriteString(fmt.Sprintf("*DENSITY\n%e\n", massDensity)) - if err != nil { - return err - } - - // Assign material to all elements - _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=Eall\n") - if err != nil { - return err - } - - // Write analysis - - _, err = f.WriteString("*STEP\n*STATIC\n") - if err != nil { - return err - } - - // Write distributed loads. - - _, err = f.WriteString("*DLOAD\n") - if err != nil { - return err - } - - // Assign gravity loading in the "positive" z-direction with magnitude 9810 to all elements. - // - // SLA 3D printing is done upside-down. 3D model is hanging from the print floor. - // That's why gravity is in "positive" z-direction. - // Here ”gravity” really stands for any acceleration vector. - // - // Refer to CalculiX solver documentation: - // http://www.dhondt.de/ccx_2.20.pdf - _, err = f.WriteString("Eall,GRAV,9810.,0.,0.,1.\n") - if err != nil { - return err - } - - // Pick element results. - - _, err = f.WriteString("*EL FILE\n") - if err != nil { - return err - } - - _, err = f.WriteString("S\n") - if err != nil { - return err - } - - // Pick node results. - - _, err = f.WriteString("*NODE FILE\n") - if err != nil { - return err - } - - _, err = f.WriteString("U\n") - if err != nil { - return err - } - - // Conclude. - - _, err = f.WriteString("*END STEP\n") - if err != nil { - return err - } - - return nil + Layer int } //----------------------------------------------------------------------------- diff --git a/render/inp.go b/render/inp.go deleted file mode 100644 index 5fc8efc70..000000000 --- a/render/inp.go +++ /dev/null @@ -1,58 +0,0 @@ -package render - -import ( - "fmt" - - "github.com/deadsy/sdfx/render/buffer" -) - -// To write different types of finite elements as ABAQUS or CalculiX `inp` file. -type Inp struct { - // Output `inp` file path. - Path string - // Output `inp` file would include start layer. - LayerStart int - // Output `inp` file would exclude end layer. - LayerEnd int - // To write only required nodes to `inp` file. - TempVBuff *buffer.VB - // Mechanical properties of 3D print resin. - MassDensity float32 - YoungModulus float32 - PoissonRatio float32 -} - -func NewInp(path string, layerStart, layerEnd int, massDensity float32, youngModulus float32, poissonRatio float32) *Inp { - return &Inp{ - Path: path, - LayerStart: layerStart, - LayerEnd: layerEnd, - TempVBuff: buffer.NewVB(), - MassDensity: massDensity, - YoungModulus: youngModulus, - PoissonRatio: poissonRatio, - } -} - -func (inp *Inp) WriteTet4(m *MeshTet4) error { - inp.writeHeader() - return nil -} - -func (inp *Inp) WriteHex8(m *MeshHex8) error { - inp.writeHeader() - return nil -} - -func (inp *Inp) WriteHex20() error { - inp.writeHeader() - return nil -} - -func (inp *Inp) writeHeader() error { - if 0 <= inp.LayerStart && inp.LayerStart < inp.LayerEnd && inp.LayerEnd <= m.layerCount() { - // Good. - } else { - return fmt.Errorf("start or end layer is beyond range") - } -} diff --git a/render/marchhex8.go b/render/marchhex8.go index 004577480..cc3b60bae 100644 --- a/render/marchhex8.go +++ b/render/marchhex8.go @@ -92,7 +92,7 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { if !anyPositive { fe := Hex8{ V: [8]v3.Vec{}, - layer: layerZ, + Layer: layerZ, } fe.V[7] = p[7] fe.V[6] = p[6] diff --git a/render/marchtet4.go b/render/marchtet4.go index b5037fa45..34a104f09 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -81,7 +81,7 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { for _, res := range result { t := Tet4{ V: [4]v3.Vec{}, - layer: layerZ, + Layer: layerZ, } t.V[3] = v3.Vec{X: 0, Y: 0, Z: 0} t.V[2] = res.V[2] diff --git a/render/tet4.go b/render/tet4.go index 07dcbf25f..3cd9dc4bc 100644 --- a/render/tet4.go +++ b/render/tet4.go @@ -1,13 +1,8 @@ package render import ( - "fmt" - "os" "sync" - "time" - "github.com/deadsy/sdfx/render/buffer" - "github.com/deadsy/sdfx/sdf" v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -17,207 +12,11 @@ import ( type Tet4 struct { // Coordinates of 4 corner nodes or vertices. V [4]v3.Vec - // The layer to which tetrahedron belongs. Layers are along Z axis. - // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store layer along Z axis. + // The Layer to which tetrahedron belongs. Layers are along Z axis. + // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store Layer along Z axis. // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. - // Sampling/marching algorithm is expected to return the layer to which a finite element belongs. - layer int -} - -//----------------------------------------------------------------------------- - -// A mesh of 4-node tetrahedra. -// A sophisticated data structure for mesh is required. -// The repeated nodes would be removed. -// The element connectivity would be created with unique nodes. -type MeshTet4 struct { - // Index buffer. - IBuff *buffer.Tet4IB - // Vertex buffer. - VBuff *buffer.VB -} - -// To get a new mesh and number of its layers along Z-axis. -func NewMeshTet4(s sdf.SDF3, r RenderTet4) (*MeshTet4, int) { - fes := ToTet4(s, r) - - _, _, layerCountZ := r.LayerCounts(s) - - m := newMeshTet4(layerCountZ) - - // Fill out the mesh with finite elements. - for _, fe := range fes { - m.addFE(fe.layer, fe.V[0], fe.V[1], fe.V[2], fe.V[3]) - } - - defer m.VBuff.DestroyHashTable() - - return m, layerCountZ -} - -func newMeshTet4(layerCount int) *MeshTet4 { - return &MeshTet4{ - IBuff: buffer.NewTet4IB(layerCount), - VBuff: buffer.NewVB(), - } -} - -// Add a finite element. -// Layer number and nodes are input. -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) addFE(l int, a, b, c, d v3.Vec) { - m.IBuff.AddTet4(l, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) -} - -func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { - return m.VBuff.Id(vert) -} - -func (m *MeshTet4) vertexCount() int { - return m.VBuff.VertexCount() -} - -func (m *MeshTet4) vertex(i uint32) v3.Vec { - return m.VBuff.Vertex(i) -} - -// Number of layers along the Z axis. -func (m *MeshTet4) layerCount() int { - return m.IBuff.LayerCount() -} - -// Number of tetrahedra on a layer. -func (m *MeshTet4) feCountOnLayer(l int) int { - return m.IBuff.FECountOnLayer(l) -} - -// Number of tetrahedra for all layers. -func (m *MeshTet4) feCount() int { - return m.IBuff.FECount() -} - -// Get a finite element. -// Layer number is input. -// Tetrahedron index on layer is input. -// Tetrahedron index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *MeshTet4) feIndicies(l, i int) (uint32, uint32, uint32, uint32) { - return m.IBuff.FEIndicies(l, i) -} - -// Get a finite element. -// Layer number is input. -// Tetrahedron index on layer is input. -// Tetrahedron index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *MeshTet4) feVertices(l, i int) (v3.Vec, v3.Vec, v3.Vec, v3.Vec) { - idx0, idx1, idx2, idx3 := m.IBuff.FEIndicies(l, i) - return m.VBuff.Vertex(idx0), m.VBuff.Vertex(idx1), m.VBuff.Vertex(idx2), m.VBuff.Vertex(idx3) -} - -// Write mesh to ABAQUS or CalculiX `inp` file. -func (m *MeshTet4) WriteInp(path string) error { - return m.WriteInpLayers(path, 0, m.layerCount()) -} - -// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. -// Result would include start layer. -// Result would exclude end layer. -func (m *MeshTet4) WriteInpLayers(path string, layerStart, layerEnd int) error { - if 0 <= layerStart && layerStart < layerEnd && layerEnd <= m.layerCount() { - // Good. - } else { - return fmt.Errorf("start or end layer is beyond range") - } - - f, err := os.Create(path) - if err != nil { - return err - } - defer f.Close() - - // Write headers. - - _, err = f.WriteString("**\n** Structure: finite elements of a 3D model.\n** Generated by: https://github.com/deadsy/sdfx\n**\n") - if err != nil { - return err - } - - _, err = f.WriteString("*HEADING\nModel: 3D model Date: " + time.Now().UTC().Format("2006-Jan-02 MST") + "\n") - if err != nil { - return err - } - - // Write nodes. - - _, err = f.WriteString("*NODE\n") - if err != nil { - return err - } - - // To write only required nodes to the file. - tempVBuff := buffer.NewVB() - defer tempVBuff.DestroyHashTable() - - var node0, node1, node2, node3 v3.Vec - var id0, id1, id2, id3 uint32 - for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.feCountOnLayer(l); i++ { - node0, node1, node2, node3 = m.feVertices(l, i) - // Get the node IDs. - id0 = tempVBuff.Id(node0) - id1 = tempVBuff.Id(node1) - id2 = tempVBuff.Id(node2) - id3 = tempVBuff.Id(node3) - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id0+1, float32(node0.X), float32(node0.Y), float32(node0.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id1+1, float32(node1.X), float32(node1.Y), float32(node1.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id2+1, float32(node2.X), float32(node2.Y), float32(node2.Z))) - if err != nil { - return err - } - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", id3+1, float32(node3.X), float32(node3.Y), float32(node3.Z))) - if err != nil { - return err - } - } - } - - // Write elements. - - _, err = f.WriteString("*ELEMENT, TYPE=C3D4, ELSET=Eall\n") - if err != nil { - return err - } - - var eleID uint32 - for l := layerStart; l < layerEnd; l++ { - for i := 0; i < m.feCountOnLayer(l); i++ { - node0, node1, node2, node3 = m.feVertices(l, i) - id0 = tempVBuff.Id(node0) - id1 = tempVBuff.Id(node1) - id2 = tempVBuff.Id(node2) - id3 = tempVBuff.Id(node3) - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, id0+1, id1+1, id2+1, id3+1)) - if err != nil { - return err - } - eleID++ - } - } - - return nil + // Sampling/marching algorithm is expected to return the Layer to which a finite element belongs. + Layer int } //----------------------------------------------------------------------------- From f051dbc60d124f75031f4b76e9100e916e78ee1c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 14:12:14 +0330 Subject: [PATCH 160/775] Consistent index buffer --- .../finiteelements/buffer/hex8indexbuffer.go | 62 ---------------- render/finiteelements/buffer/indexbuffer.go | 70 +++++++++++++++++++ .../finiteelements/buffer/tet4indexbuffer.go | 57 --------------- render/finiteelements/mesh/hex8.go | 8 +-- render/finiteelements/mesh/tet4.go | 27 +++---- 5 files changed, 88 insertions(+), 136 deletions(-) delete mode 100644 render/finiteelements/buffer/hex8indexbuffer.go create mode 100644 render/finiteelements/buffer/indexbuffer.go delete mode 100644 render/finiteelements/buffer/tet4indexbuffer.go diff --git a/render/finiteelements/buffer/hex8indexbuffer.go b/render/finiteelements/buffer/hex8indexbuffer.go deleted file mode 100644 index a713eb841..000000000 --- a/render/finiteelements/buffer/hex8indexbuffer.go +++ /dev/null @@ -1,62 +0,0 @@ -package buffer - -// Index buffer for 8-node hexahedra. -type Hex8IB struct { - // Every 8 indices would correspond to a hexahedron. - // It's kept low-level for performance. - // Tetrahedra are stored by their layer on Z axis. - I [][]uint32 -} - -func NewHex8IB(layerCount int) *Hex8IB { - ib := Hex8IB{ - I: [][]uint32{}, - } - - // Initialize. - ib.I = make([][]uint32, layerCount) - for l := 0; l < layerCount; l++ { - ib.I[l] = make([]uint32, 0) - } - - return &ib -} - -// Add a finite element to buffer. -// Layer number and nodes are input. -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (ib *Hex8IB) AddFE(l int, nodes [8]uint32) { - ib.I[l] = append(ib.I[l], nodes[:]...) -} - -// Number of layers along the Z axis. -func (ib *Hex8IB) LayerCount() int { - return len(ib.I) -} - -// Number of finite elements on a layer. -func (ib *Hex8IB) FECountOnLayer(l int) int { - return len(ib.I[l]) / 8 -} - -// Number of finite elements for all layers. -func (ib *Hex8IB) FECount() int { - var count int - for _, l := range ib.I { - count += len(l) / 8 - } - return count -} - -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of FE on layer. -// Don't return error to increase performance. -func (ib *Hex8IB) FEIndicies(l, i int) [8]uint32 { - indices := [8]uint32{} - for n := 0; n < 8; n++ { - indices[n] = ib.I[l][i*8+n] - } - return indices -} diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go new file mode 100644 index 000000000..44a6b6559 --- /dev/null +++ b/render/finiteelements/buffer/indexbuffer.go @@ -0,0 +1,70 @@ +package buffer + +// Index buffer for a mesh of finite elements. +type IB struct { + // Every NodesPerElement indices would correspond to a finite element. + // It's kept low-level for performance. + // Finite elements are stored by their layer on Z axis. + I [][]uint32 + NodesPerElement int +} + +func NewIB(layerCount, nodesPerElement int) *IB { + ib := IB{ + I: [][]uint32{}, + NodesPerElement: nodesPerElement, + } + + // Initialize. + ib.I = make([][]uint32, layerCount) + for l := 0; l < layerCount; l++ { + ib.I[l] = make([]uint32, 0) + } + + return &ib +} + +// Add a finite element to buffer. +// Layer number and nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (ib *IB) AddFE(l int, nodes []uint32) { + if len(nodes) != ib.NodesPerElement { + // Don't return error. + // Since this function is going to be called by heavy loops. + // More efficient this way. Right? + panic("bad sizes: nodes of finite element") + } + ib.I[l] = append(ib.I[l], nodes...) +} + +// Number of layers along the Z axis. +func (ib *IB) LayerCount() int { + return len(ib.I) +} + +// Number of finite elements on a layer. +func (ib *IB) FECountOnLayer(l int) int { + return len(ib.I[l]) / ib.NodesPerElement +} + +// Number of finite elements for all layers. +func (ib *IB) FECount() int { + var count int + for _, l := range ib.I { + count += len(l) / ib.NodesPerElement + } + return count +} + +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of FE on layer. +// Don't return error to increase performance. +func (ib *IB) FEIndicies(l, i int) []uint32 { + indices := make([]uint32, ib.NodesPerElement) + for n := 0; n < ib.NodesPerElement; n++ { + indices[n] = ib.I[l][i*ib.NodesPerElement+n] + } + return indices +} diff --git a/render/finiteelements/buffer/tet4indexbuffer.go b/render/finiteelements/buffer/tet4indexbuffer.go deleted file mode 100644 index 4e0bafda1..000000000 --- a/render/finiteelements/buffer/tet4indexbuffer.go +++ /dev/null @@ -1,57 +0,0 @@ -package buffer - -// Index buffer for 4-node tetrahedra. -type Tet4IB struct { - // Every 4 indices would correspond to a tetrahedron. - // It's kept low-level for performance. - // Tetrahedra are stored by their layer on Z axis. - I [][]uint32 -} - -func NewTet4IB(layerCount int) *Tet4IB { - ib := Tet4IB{ - I: [][]uint32{}, - } - - // Initialize. - ib.I = make([][]uint32, layerCount) - for l := 0; l < layerCount; l++ { - ib.I[l] = make([]uint32, 0) - } - - return &ib -} - -// Layer number and 4 nodes are input. -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (ib *Tet4IB) AddTet4(l int, a, b, c, d uint32) { - ib.I[l] = append(ib.I[l], a, b, c, d) -} - -// Number of layers along the Z axis. -func (ib *Tet4IB) LayerCount() int { - return len(ib.I) -} - -// Number of tetrahedra on a layer. -func (ib *Tet4IB) FECountOnLayer(l int) int { - return len(ib.I[l]) / 4 -} - -// Number of tetrahedra for all layers. -func (ib *Tet4IB) FECount() int { - var count int - for _, l := range ib.I { - count += len(l) / 4 - } - return count -} - -// Layer number is input. -// Tetrahedron index on layer is input. -// Tetrahedron index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (ib *Tet4IB) FEIndicies(l, i int) (uint32, uint32, uint32, uint32) { - return ib.I[l][i*4], ib.I[l][i*4+1], ib.I[l][i*4+2], ib.I[l][i*4+3] -} diff --git a/render/finiteelements/mesh/hex8.go b/render/finiteelements/mesh/hex8.go index a39c32f99..3616c04af 100644 --- a/render/finiteelements/mesh/hex8.go +++ b/render/finiteelements/mesh/hex8.go @@ -13,7 +13,7 @@ import ( // The element connectivity would be created with unique nodes. type MeshHex8 struct { // Index buffer. - IBuff *buffer.Hex8IB + IBuff *buffer.IB // Vertex buffer. VBuff *buffer.VB } @@ -42,7 +42,7 @@ func NewMeshHex8(s sdf.SDF3, r render.RenderHex8) (*MeshHex8, int) { func newMeshHex8(layerCount int) *MeshHex8 { return &MeshHex8{ - IBuff: buffer.NewHex8IB(layerCount), + IBuff: buffer.NewIB(layerCount, 8), VBuff: buffer.NewVB(), } } @@ -60,7 +60,7 @@ func (m *MeshHex8) addFE(l int, nodes [8]v3.Vec) { for n := 0; n < 8; n++ { indices[n] = m.addVertex(nodes[n]) } - m.IBuff.AddFE(l, indices) + m.IBuff.AddFE(l, indices[:]) } func (m *MeshHex8) addVertex(vert v3.Vec) uint32 { @@ -95,7 +95,7 @@ func (m *MeshHex8) feCount() int { // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex8) feIndicies(l, i int) [8]uint32 { +func (m *MeshHex8) feIndicies(l, i int) []uint32 { return m.IBuff.FEIndicies(l, i) } diff --git a/render/finiteelements/mesh/tet4.go b/render/finiteelements/mesh/tet4.go index 0e9bc4173..6c39e841c 100644 --- a/render/finiteelements/mesh/tet4.go +++ b/render/finiteelements/mesh/tet4.go @@ -13,7 +13,7 @@ import ( // The element connectivity would be created with unique nodes. type MeshTet4 struct { // Index buffer. - IBuff *buffer.Tet4IB + IBuff *buffer.IB // Vertex buffer. VBuff *buffer.VB } @@ -28,7 +28,7 @@ func NewMeshTet4(s sdf.SDF3, r render.RenderTet4) (*MeshTet4, int) { // Fill out the mesh with finite elements. for _, fe := range fes { - m.addFE(fe.Layer, fe.V[0], fe.V[1], fe.V[2], fe.V[3]) + m.addFE(fe.Layer, [4]v3.Vec{fe.V[0], fe.V[1], fe.V[2], fe.V[3]}) } defer m.VBuff.DestroyHashTable() @@ -38,7 +38,7 @@ func NewMeshTet4(s sdf.SDF3, r render.RenderTet4) (*MeshTet4, int) { func newMeshTet4(layerCount int) *MeshTet4 { return &MeshTet4{ - IBuff: buffer.NewTet4IB(layerCount), + IBuff: buffer.NewIB(layerCount, 4), VBuff: buffer.NewVB(), } } @@ -51,8 +51,12 @@ func (m *MeshTet4) NodesPerElement() int { // Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) addFE(l int, a, b, c, d v3.Vec) { - m.IBuff.AddTet4(l, m.addVertex(a), m.addVertex(b), m.addVertex(c), m.addVertex(d)) +func (m *MeshTet4) addFE(l int, nodes [4]v3.Vec) { + indices := [4]uint32{} + for n := 0; n < 4; n++ { + indices[n] = m.addVertex(nodes[n]) + } + m.IBuff.AddFE(l, indices[:]) } func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { @@ -87,7 +91,7 @@ func (m *MeshTet4) feCount() int { // Tetrahedron index on layer is input. // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) feIndicies(l, i int) (uint32, uint32, uint32, uint32) { +func (m *MeshTet4) feIndicies(l, i int) []uint32 { return m.IBuff.FEIndicies(l, i) } @@ -97,14 +101,11 @@ func (m *MeshTet4) feIndicies(l, i int) (uint32, uint32, uint32, uint32) { // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. func (m *MeshTet4) feVertices(l, i int) []v3.Vec { - idx0, idx1, idx2, idx3 := m.IBuff.FEIndicies(l, i) + indices := m.IBuff.FEIndicies(l, i) vertices := make([]v3.Vec, 4) - - vertices[0] = m.VBuff.Vertex(idx0) - vertices[1] = m.VBuff.Vertex(idx1) - vertices[2] = m.VBuff.Vertex(idx2) - vertices[3] = m.VBuff.Vertex(idx3) - + for n := 0; n < 4; n++ { + vertices[n] = m.VBuff.Vertex(indices[n]) + } return vertices } From 7f5acd5662e761dca4f3f10b735df5d872b78e1a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 14:16:11 +0330 Subject: [PATCH 161/775] Double-check & throw panic --- render/finiteelements/buffer/indexbuffer.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index 44a6b6559..ee6d94140 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -10,6 +10,10 @@ type IB struct { } func NewIB(layerCount, nodesPerElement int) *IB { + if nodesPerElement < 1 { + panic("nodes per finite element must be positive") + } + ib := IB{ I: [][]uint32{}, NodesPerElement: nodesPerElement, From 252db86564bf4fd0f5df6c4329f232b82812bcca Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 14:40:36 +0330 Subject: [PATCH 162/775] Redesign: more consistent marching cubes algorithm --- examples/finite_elements/main.go | 4 +- render/finiteelements/mesh/hex8.go | 2 +- render/finiteelements/mesh/tet4.go | 2 +- render/marchfe.go | 77 ++++++++++++++++++++++++++++++ render/marchhex8.go | 55 --------------------- render/marchtet4.go | 55 --------------------- render/render.go | 24 ++++------ 7 files changed, 89 insertions(+), 130 deletions(-) create mode 100644 render/marchfe.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 3d9591015..712a7ff83 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -26,7 +26,7 @@ import ( // Written file can be used by ABAQUS or CalculiX. func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := mesh.NewMeshTet4(s, render.NewMarchingTet4Uniform(resolution)) + m, _ := mesh.NewMeshTet4(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 lyrEnd := 20 @@ -46,7 +46,7 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Written file can be used by ABAQUS or CalculiX. func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := mesh.NewMeshHex8(s, render.NewMarchingHex8Uniform(resolution)) + m, _ := mesh.NewMeshHex8(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 lyrEnd := 20 diff --git a/render/finiteelements/mesh/hex8.go b/render/finiteelements/mesh/hex8.go index 3616c04af..7a0073eb6 100644 --- a/render/finiteelements/mesh/hex8.go +++ b/render/finiteelements/mesh/hex8.go @@ -19,7 +19,7 @@ type MeshHex8 struct { } // To get a new mesh and number of its layers along Z-axis. -func NewMeshHex8(s sdf.SDF3, r render.RenderHex8) (*MeshHex8, int) { +func NewMeshHex8(s sdf.SDF3, r render.RenderFE) (*MeshHex8, int) { fes := render.ToHex8(s, r) _, _, layerCountZ := r.LayerCounts(s) diff --git a/render/finiteelements/mesh/tet4.go b/render/finiteelements/mesh/tet4.go index 6c39e841c..12522112e 100644 --- a/render/finiteelements/mesh/tet4.go +++ b/render/finiteelements/mesh/tet4.go @@ -19,7 +19,7 @@ type MeshTet4 struct { } // To get a new mesh and number of its layers along Z-axis. -func NewMeshTet4(s sdf.SDF3, r render.RenderTet4) (*MeshTet4, int) { +func NewMeshTet4(s sdf.SDF3, r render.RenderFE) (*MeshTet4, int) { fes := render.ToTet4(s, r) _, _, layerCountZ := r.LayerCounts(s) diff --git a/render/marchfe.go b/render/marchfe.go new file mode 100644 index 000000000..a3b7ceb1f --- /dev/null +++ b/render/marchfe.go @@ -0,0 +1,77 @@ +package render + +import ( + "fmt" + + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" +) + +//----------------------------------------------------------------------------- + +// MarchingCubesFEUniform renders using marching cubes with uniform space sampling. +type MarchingCubesFEUniform struct { + meshCells int // number of cells on the longest axis of bounding box. e.g 200 +} + +// NewMarchingCubesFEUniform returns a RenderHex8 object. +func NewMarchingCubesFEUniform(meshCells int) *MarchingCubesFEUniform { + return &MarchingCubesFEUniform{ + meshCells: meshCells, + } +} + +// Info returns a string describing the rendered volume. +func (r *MarchingCubesFEUniform) Info(s sdf.SDF3) string { + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + cells := conv.V3ToV3i(bb1Size) + return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) +} + +// To get the layer counts which are consistent with loops of marching algorithm. +func (r *MarchingCubesFEUniform) LayerCounts(s sdf.SDF3) (int, int, int) { + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + size := bb.Size() + steps := conv.V3ToV3i(size.DivScalar(meshInc).Ceil()) + return steps.X, steps.Y, steps.Z +} + +// Render produces a finite elements mesh over the bounding volume of an sdf3. +// Finite elements are in the shape of tetrahedra. +func (r *MarchingCubesFEUniform) RenderTet4(s sdf.SDF3, output chan<- []*Tet4) { + // work out the region we will sample + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + output <- marchingCubesTet4(s, bb, meshInc) +} + +// Render produces a finite elements mesh over the bounding volume of an sdf3. +// Finite elements are in the shape of hexahedra. +func (r *MarchingCubesFEUniform) RenderHex8(s sdf.SDF3, output chan<- []*Hex8) { + // work out the region we will sample + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + output <- marchingCubesHex8(s, bb, meshInc) +} + +//----------------------------------------------------------------------------- diff --git a/render/marchhex8.go b/render/marchhex8.go index cc3b60bae..38bd2e856 100644 --- a/render/marchhex8.go +++ b/render/marchhex8.go @@ -1,8 +1,6 @@ package render import ( - "fmt" - "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" @@ -109,56 +107,3 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { } //----------------------------------------------------------------------------- - -// MarchingHex8Uniform renders using marching cubes with uniform space sampling. -type MarchingHex8Uniform struct { - meshCells int // number of cells on the longest axis of bounding box. e.g 200 -} - -// NewMarchingHex8Uniform returns a RenderHex8 object. -func NewMarchingHex8Uniform(meshCells int) *MarchingHex8Uniform { - return &MarchingHex8Uniform{ - meshCells: meshCells, - } -} - -// Info returns a string describing the rendered volume. -func (r *MarchingHex8Uniform) Info(s sdf.SDF3) string { - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - cells := conv.V3ToV3i(bb1Size) - return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) -} - -// To get the layer counts which are consistent with loops of marching algorithm. -func (r *MarchingHex8Uniform) LayerCounts(s sdf.SDF3) (int, int, int) { - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - bb1Size = bb1Size.MulScalar(meshInc) - bb := sdf.NewBox3(bb0.Center(), bb1Size) - size := bb.Size() - steps := conv.V3ToV3i(size.DivScalar(meshInc).Ceil()) - return steps.X, steps.Y, steps.Z -} - -// Render produces a finite elements mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of hexahedra. -func (r *MarchingHex8Uniform) Render(s sdf.SDF3, output chan<- []*Hex8) { - // work out the region we will sample - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - bb1Size = bb1Size.MulScalar(meshInc) - bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingCubesHex8(s, bb, meshInc) -} - -//----------------------------------------------------------------------------- diff --git a/render/marchtet4.go b/render/marchtet4.go index 34a104f09..b63c316c5 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -1,8 +1,6 @@ package render import ( - "fmt" - "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" @@ -94,56 +92,3 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { } //----------------------------------------------------------------------------- - -// MarchingTet4Uniform renders using marching Tetrahedra with uniform space sampling. -type MarchingTet4Uniform struct { - meshCells int // number of cells on the longest axis of bounding box. e.g 200 -} - -// NewMarchingTet4Uniform returns a RenderTet4 object. -func NewMarchingTet4Uniform(meshCells int) *MarchingTet4Uniform { - return &MarchingTet4Uniform{ - meshCells: meshCells, - } -} - -// Info returns a string describing the rendered volume. -func (r *MarchingTet4Uniform) Info(s sdf.SDF3) string { - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - cells := conv.V3ToV3i(bb1Size) - return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) -} - -// To get the layer counts which are consistent with loops of marching algorithm. -func (r *MarchingTet4Uniform) LayerCounts(s sdf.SDF3) (int, int, int) { - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - bb1Size = bb1Size.MulScalar(meshInc) - bb := sdf.NewBox3(bb0.Center(), bb1Size) - size := bb.Size() - steps := conv.V3ToV3i(size.DivScalar(meshInc).Ceil()) - return steps.X, steps.Y, steps.Z -} - -// Render produces a finite elements mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of tetrahedra. -func (r *MarchingTet4Uniform) Render(s sdf.SDF3, output chan<- []*Tet4) { - // work out the region we will sample - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - bb1Size = bb1Size.MulScalar(meshInc) - bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingCubesTet4(s, bb, meshInc) -} - -//----------------------------------------------------------------------------- diff --git a/render/render.go b/render/render.go index 147023da7..42ec712da 100644 --- a/render/render.go +++ b/render/render.go @@ -29,18 +29,10 @@ type Render2 interface { Info(s sdf.SDF2) string } -// RenderTet4 renders a finite element mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of 4-node tetrahedra. -type RenderTet4 interface { - Render(sdf3 sdf.SDF3, output chan<- []*Tet4) - Info(sdf3 sdf.SDF3) string - LayerCounts(sdf3 sdf.SDF3) (int, int, int) -} - -// RenderHex8 renders a finite element mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of 8-node hexahedra. -type RenderHex8 interface { - Render(sdf3 sdf.SDF3, output chan<- []*Hex8) +// RenderFE renders a finite element mesh over the bounding volume of an sdf3. +type RenderFE interface { + RenderTet4(sdf3 sdf.SDF3, output chan<- []*Tet4) + RenderHex8(sdf3 sdf.SDF3, output chan<- []*Hex8) Info(sdf3 sdf.SDF3) string LayerCounts(sdf3 sdf.SDF3) (int, int, int) } @@ -71,7 +63,7 @@ func ToTriangles( // ToTet4 renders an SDF3 to finite elements in the shape of 4-node tetrahedra. func ToTet4( s sdf.SDF3, // sdf3 to render - r RenderTet4, // rendering method + r RenderFE, // rendering method ) []Tet4 { fmt.Printf("rendering %s\n", r.Info(s)) @@ -87,7 +79,7 @@ func ToTet4( output := writeTet4(&wg, &tet4s) // run the renderer - r.Render(s, output) + r.RenderTet4(s, output) // stop the writer reading on the channel close(output) // wait for the file write to complete @@ -101,7 +93,7 @@ func ToTet4( // ToHex8 renders an SDF3 to finite elements in the shape of 8-node hexahedra. func ToHex8( s sdf.SDF3, // sdf3 to render - r RenderHex8, // rendering method + r RenderFE, // rendering method ) []Hex8 { fmt.Printf("rendering %s\n", r.Info(s)) @@ -117,7 +109,7 @@ func ToHex8( output := writeHex8(&wg, &hex8s) // run the renderer - r.Render(s, output) + r.RenderHex8(s, output) // stop the writer reading on the channel close(output) // wait for the file write to complete From a621aad8045bc11af0a55be018e1ccc011388922 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 14:59:42 +0330 Subject: [PATCH 163/775] New hex20 finite element --- render/finiteelements/mesh/hex20.go | 146 ++++++++++++++++++++++++++++ render/hex20.go | 44 +++++++++ render/marchfe.go | 14 +++ render/marchhex20.go | 109 +++++++++++++++++++++ render/render.go | 31 ++++++ 5 files changed, 344 insertions(+) create mode 100644 render/finiteelements/mesh/hex20.go create mode 100644 render/hex20.go create mode 100644 render/marchhex20.go diff --git a/render/finiteelements/mesh/hex20.go b/render/finiteelements/mesh/hex20.go new file mode 100644 index 000000000..6b9ff45c7 --- /dev/null +++ b/render/finiteelements/mesh/hex20.go @@ -0,0 +1,146 @@ +package mesh + +import ( + "github.com/deadsy/sdfx/render" + "github.com/deadsy/sdfx/render/finiteelements/buffer" + "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// A mesh of 20-node hexahedra. +// A sophisticated data structure for mesh is required. +// The repeated nodes would be removed. +// The element connectivity would be created with unique nodes. +type MeshHex20 struct { + // Index buffer. + IBuff *buffer.IB + // Vertex buffer. + VBuff *buffer.VB +} + +// To get a new mesh and number of its layers along Z-axis. +func NewMeshHex20(s sdf.SDF3, r render.RenderFE) (*MeshHex20, int) { + fes := render.ToHex20(s, r) + + _, _, layerCountZ := r.LayerCounts(s) + + m := newMeshHex20(layerCountZ) + + // Fill out the mesh with finite elements. + for _, fe := range fes { + nodes := [20]v3.Vec{} + for n := 0; n < 20; n++ { + nodes[n] = fe.V[n] + } + m.addFE(fe.Layer, nodes) + } + + defer m.VBuff.DestroyHashTable() + + return m, layerCountZ +} + +func newMeshHex20(layerCount int) *MeshHex20 { + return &MeshHex20{ + IBuff: buffer.NewIB(layerCount, 20), + VBuff: buffer.NewVB(), + } +} + +func (m *MeshHex20) NodesPerElement() int { + return 20 +} + +// Add a finite element to mesh. +// Layer number and nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (m *MeshHex20) addFE(l int, nodes [20]v3.Vec) { + indices := [20]uint32{} + for n := 0; n < 20; n++ { + indices[n] = m.addVertex(nodes[n]) + } + m.IBuff.AddFE(l, indices[:]) +} + +func (m *MeshHex20) addVertex(vert v3.Vec) uint32 { + return m.VBuff.Id(vert) +} + +func (m *MeshHex20) vertexCount() int { + return m.VBuff.VertexCount() +} + +func (m *MeshHex20) vertex(i uint32) v3.Vec { + return m.VBuff.Vertex(i) +} + +// Number of layers along the Z axis. +func (m *MeshHex20) layerCount() int { + return m.IBuff.LayerCount() +} + +// Number of finite elements on a layer. +func (m *MeshHex20) feCountOnLayer(l int) int { + return m.IBuff.FECountOnLayer(l) +} + +// Number of finite elements for all layers. +func (m *MeshHex20) feCount() int { + return m.IBuff.FECount() +} + +// Get a finite element. +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *MeshHex20) feIndicies(l, i int) []uint32 { + return m.IBuff.FEIndicies(l, i) +} + +// Get a finite element. +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *MeshHex20) feVertices(l, i int) []v3.Vec { + indices := m.IBuff.FEIndicies(l, i) + vertices := make([]v3.Vec, 20) + for n := 0; n < 20; n++ { + vertices[n] = m.VBuff.Vertex(indices[n]) + } + return vertices +} + +// Write mesh to ABAQUS or CalculiX `inp` file. +// Units of measurement are mm,N,s,K. +// Refer to https://engineering.stackexchange.com/q/54454/15178 +func (m *MeshHex20) WriteInp( + path string, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) +} + +// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +// Result would include start layer. +// Result would exclude end layer. +// Units of measurement are mm,N,s,K. +// Refer to https://engineering.stackexchange.com/q/54454/15178 +func (m *MeshHex20) WriteInpLayers( + path string, + layerStart, layerEnd int, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) + return inp.Write() +} + +//----------------------------------------------------------------------------- diff --git a/render/hex20.go b/render/hex20.go new file mode 100644 index 000000000..529795d37 --- /dev/null +++ b/render/hex20.go @@ -0,0 +1,44 @@ +package render + +import ( + "sync" + + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// Hex20 is a 3D hexahedron consisting of 20 nodes. +// It's a kind of finite element, FE. +// https://en.wikipedia.org/wiki/Hexahedron +type Hex20 struct { + // Coordinates of 20 corner nodes or vertices. + V [20]v3.Vec + // The layer to which tetrahedron belongs. Layers are along Z axis. + // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store layer along Z axis. + // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. + // Sampling/marching algorithm is expected to return the layer to which a finite element belongs. + Layer int +} + +//----------------------------------------------------------------------------- + +// writeHex20 writes a stream of finite elements to an array. +func writeHex20(wg *sync.WaitGroup, hex20s *[]Hex20) chan<- []*Hex20 { + // External code writes to this channel. + // This goroutine reads the channel and stores finite elements. + c := make(chan []*Hex20) + + wg.Add(1) + go func() { + defer wg.Done() + // read finite elements from the channel and handle them + for fes := range c { + for _, fe := range fes { + *hex20s = append(*hex20s, *fe) + } + } + }() + + return c +} + +//----------------------------------------------------------------------------- diff --git a/render/marchfe.go b/render/marchfe.go index a3b7ceb1f..af1e69760 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -74,4 +74,18 @@ func (r *MarchingCubesFEUniform) RenderHex8(s sdf.SDF3, output chan<- []*Hex8) { output <- marchingCubesHex8(s, bb, meshInc) } +// Render produces a finite elements mesh over the bounding volume of an sdf3. +// Finite elements are in the shape of hexahedra. +func (r *MarchingCubesFEUniform) RenderHex20(s sdf.SDF3, output chan<- []*Hex20) { + // work out the region we will sample + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + output <- marchingCubesHex20(s, bb, meshInc) +} + //----------------------------------------------------------------------------- diff --git a/render/marchhex20.go b/render/marchhex20.go new file mode 100644 index 000000000..45bc5c24d --- /dev/null +++ b/render/marchhex20.go @@ -0,0 +1,109 @@ +package render + +import ( + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +//----------------------------------------------------------------------------- + +func marchingCubesHex20(s sdf.SDF3, box sdf.Box3, step float64) []*Hex20 { + + var fes []*Hex20 + size := box.Size() + base := box.Min + steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) + inc := size.Div(conv.V3iToV3(steps)) + + // start the evaluation routines + evalRoutines() + + // create the SDF layer cache + l := newLayerYZ(base, inc, steps) + // evaluate the SDF for x = 0 + l.Evaluate(s, 0) + + nx, ny, nz := steps.X, steps.Y, steps.Z + dx, dy, dz := inc.X, inc.Y, inc.Z + + var p v3.Vec + p.X = base.X + for x := 0; x < nx; x++ { + // read the x + 1 layer + l.Evaluate(s, x+1) + // process all cubes in the x and x + 1 layers + p.Y = base.Y + for y := 0; y < ny; y++ { + p.Z = base.Z + for z := 0; z < nz; z++ { + x0, y0, z0 := p.X, p.Y, p.Z + x1, y1, z1 := x0+dx, y0+dy, z0+dz + corners := [8]v3.Vec{ + {x0, y0, z0}, + {x1, y0, z0}, + {x1, y1, z0}, + {x0, y1, z0}, + {x0, y0, z1}, + {x1, y0, z1}, + {x1, y1, z1}, + {x0, y1, z1}} + values := [8]float64{ + l.Get(0, y, z), + l.Get(1, y, z), + l.Get(1, y+1, z), + l.Get(0, y+1, z), + l.Get(0, y, z+1), + l.Get(1, y, z+1), + l.Get(1, y+1, z+1), + l.Get(0, y+1, z+1)} + fes = append(fes, mcToHex20(corners, values, 0, z)...) + p.Z += dz + } + p.Y += dy + } + p.X += dx + } + + return fes +} + +//----------------------------------------------------------------------------- + +func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex20 { + result := make([]*Hex20, 0) + + anyPositive := false + for i := 0; i < 8; i++ { + if v[i] > 0 { + anyPositive = true + break + } + } + + // Create a finite element if all 8 values are non-positive. + // Finite element is inside the 3D model if all values are non-positive. + // Of course, some spaces are missed by this approach. + // + // TODO: Come up with a more sophisticated approach? + + if !anyPositive { + fe := Hex20{ + V: [20]v3.Vec{}, + Layer: layerZ, + } + fe.V[7] = p[7] + fe.V[6] = p[6] + fe.V[5] = p[5] + fe.V[4] = p[4] + fe.V[3] = p[3] + fe.V[2] = p[2] + fe.V[1] = p[1] + fe.V[0] = p[0] + result = append(result, &fe) + } + + return result +} + +//----------------------------------------------------------------------------- diff --git a/render/render.go b/render/render.go index 42ec712da..1b8f46a37 100644 --- a/render/render.go +++ b/render/render.go @@ -33,6 +33,7 @@ type Render2 interface { type RenderFE interface { RenderTet4(sdf3 sdf.SDF3, output chan<- []*Tet4) RenderHex8(sdf3 sdf.SDF3, output chan<- []*Hex8) + RenderHex20(sdf3 sdf.SDF3, output chan<- []*Hex20) Info(sdf3 sdf.SDF3) string LayerCounts(sdf3 sdf.SDF3) (int, int, int) } @@ -120,6 +121,36 @@ func ToHex8( //----------------------------------------------------------------------------- +// ToHex20 renders an SDF3 to finite elements in the shape of 8-node hexahedra. +func ToHex20( + s sdf.SDF3, // sdf3 to render + r RenderFE, // rendering method +) []Hex20 { + fmt.Printf("rendering %s\n", r.Info(s)) + + layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) + fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) + + // Will be filled by the rendering. + hex20s := make([]Hex20, 0) + + var wg sync.WaitGroup + + // Get the channel to be written to. + output := writeHex20(&wg, &hex20s) + + // run the renderer + r.RenderHex20(s, output) + // stop the writer reading on the channel + close(output) + // wait for the file write to complete + wg.Wait() + + return hex20s +} + +//----------------------------------------------------------------------------- + // ToSTL renders an SDF3 to an STL file. func ToSTL( s sdf.SDF3, // sdf3 to render From e3f083fab3e79e01cbc8b40d926c2c177e116659 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 15:01:03 +0330 Subject: [PATCH 164/775] Rename: more consistent --- render/marchhex8.go | 6 +++--- render/marchtet4.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/render/marchhex8.go b/render/marchhex8.go index 38bd2e856..513a5bff0 100644 --- a/render/marchhex8.go +++ b/render/marchhex8.go @@ -10,7 +10,7 @@ import ( func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { - var tetrahedra []*Hex8 + var fes []*Hex8 size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) @@ -57,7 +57,7 @@ func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { l.Get(1, y, z+1), l.Get(1, y+1, z+1), l.Get(0, y+1, z+1)} - tetrahedra = append(tetrahedra, mcToHex8(corners, values, 0, z)...) + fes = append(fes, mcToHex8(corners, values, 0, z)...) p.Z += dz } p.Y += dy @@ -65,7 +65,7 @@ func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { p.X += dx } - return tetrahedra + return fes } //----------------------------------------------------------------------------- diff --git a/render/marchtet4.go b/render/marchtet4.go index b63c316c5..d9cad9f2e 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -10,7 +10,7 @@ import ( func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { - var tetrahedra []*Tet4 + var fes []*Tet4 size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) @@ -57,7 +57,7 @@ func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { l.Get(1, y, z+1), l.Get(1, y+1, z+1), l.Get(0, y+1, z+1)} - tetrahedra = append(tetrahedra, mcToTet4(corners, values, 0, z)...) + fes = append(fes, mcToTet4(corners, values, 0, z)...) p.Z += dz } p.Y += dy @@ -65,7 +65,7 @@ func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { p.X += dx } - return tetrahedra + return fes } //----------------------------------------------------------------------------- From 0c0c2005cf2d7d2004b3bdc96edede3296073b71 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 15:02:21 +0330 Subject: [PATCH 165/775] Rename: consistent --- render/render.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/render/render.go b/render/render.go index 1b8f46a37..7811b33ab 100644 --- a/render/render.go +++ b/render/render.go @@ -72,12 +72,12 @@ func ToTet4( fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) // Will be filled by the rendering. - tet4s := make([]Tet4, 0) + fes := make([]Tet4, 0) var wg sync.WaitGroup // Get the channel to be written to. - output := writeTet4(&wg, &tet4s) + output := writeTet4(&wg, &fes) // run the renderer r.RenderTet4(s, output) @@ -86,7 +86,7 @@ func ToTet4( // wait for the file write to complete wg.Wait() - return tet4s + return fes } //----------------------------------------------------------------------------- @@ -102,12 +102,12 @@ func ToHex8( fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) // Will be filled by the rendering. - hex8s := make([]Hex8, 0) + fes := make([]Hex8, 0) var wg sync.WaitGroup // Get the channel to be written to. - output := writeHex8(&wg, &hex8s) + output := writeHex8(&wg, &fes) // run the renderer r.RenderHex8(s, output) @@ -116,7 +116,7 @@ func ToHex8( // wait for the file write to complete wg.Wait() - return hex8s + return fes } //----------------------------------------------------------------------------- @@ -132,12 +132,12 @@ func ToHex20( fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) // Will be filled by the rendering. - hex20s := make([]Hex20, 0) + fes := make([]Hex20, 0) var wg sync.WaitGroup // Get the channel to be written to. - output := writeHex20(&wg, &hex20s) + output := writeHex20(&wg, &fes) // run the renderer r.RenderHex20(s, output) @@ -146,7 +146,7 @@ func ToHex20( // wait for the file write to complete wg.Wait() - return hex20s + return fes } //----------------------------------------------------------------------------- From 503a68ef3cd07a895a2815d2ebccba791b2a033c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 15:10:35 +0330 Subject: [PATCH 166/775] Write 20 nodes for each hex20 --- render/finiteelements/mesh/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 02ba1f4c0..38d92df97 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -237,7 +237,7 @@ func (inp *Inp) writeElements(f *os.File) error { } else if inp.Mesh.NodesPerElement() == 8 { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) } else if inp.Mesh.NodesPerElement() == 20 { - // TODO. + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1, ids[10]+1, ids[11]+1, ids[12]+1, ids[13]+1, ids[14]+1, ids[15]+1, ids[16]+1, ids[17]+1, ids[18]+1, ids[19]+1)) } if err != nil { From 22e7e1dcfbdc8add9dd602edafd73b0ce08d314d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 15:11:05 +0330 Subject: [PATCH 167/775] Hex20 example --- examples/finite_elements/main.go | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 712a7ff83..68f13ff38 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -69,6 +69,36 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { return nil } +// 20-node hexahedral elements. +// +// Render SDF3 to finite elements. +// Write finite elements to an `inp` file. +// Written file can be used by ABAQUS or CalculiX. +func hex20FiniteElements(s sdf.SDF3, resolution int, pth string) error { + // Create a mesh out of finite elements. + m, _ := mesh.NewMeshHex20(s, render.NewMarchingCubesFEUniform(resolution)) + + lyrStart := 0 + lyrEnd := 20 + + // Write just some layers of mesh to a file. + // + // Units are mm,N,sec. + // Force per area = N/mm2 or MPa + // Mass density = Ns2/mm4 + // Refer to the "Units" chapter of: + // http://www.dhondt.de/ccx_2.20.pdf + // + // Mechanical properties are based on typical SLA resins. + // + // TODO: Correct resin specifications. + err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + if err != nil { + return err + } + return nil +} + func main() { stl := "../../files/teapot.stl" @@ -93,4 +123,9 @@ func main() { if err != nil { log.Fatalf("error: %s", err) } + + err = hex20FiniteElements(teapotSdf, 80, "teapot-hex20.inp") + if err != nil { + log.Fatalf("error: %s", err) + } } From 41d4e38d2863a748d34b7e6728d0b7a6a94e3a64 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 15:26:25 +0330 Subject: [PATCH 168/775] Compute hex20 nodes coordinates --- render/marchhex20.go | 22 ++++++++++++++++++++++ render/marchhex8.go | 4 ++++ 2 files changed, 26 insertions(+) diff --git a/render/marchhex20.go b/render/marchhex20.go index 45bc5c24d..e9a33b666 100644 --- a/render/marchhex20.go +++ b/render/marchhex20.go @@ -92,6 +92,11 @@ func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex20 { V: [20]v3.Vec{}, Layer: layerZ, } + + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + + // Points on cube corners: fe.V[7] = p[7] fe.V[6] = p[6] fe.V[5] = p[5] @@ -100,6 +105,23 @@ func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex20 { fe.V[2] = p[2] fe.V[1] = p[1] fe.V[0] = p[0] + + // Points on cube edges: + fe.V[8] = p[0].Add(p[1]).MulScalar(0.5) + fe.V[9] = p[1].Add(p[2]).MulScalar(0.5) + fe.V[10] = p[2].Add(p[3]).MulScalar(0.5) + fe.V[11] = p[3].Add(p[0]).MulScalar(0.5) + + fe.V[12] = p[4].Add(p[5]).MulScalar(0.5) + fe.V[13] = p[5].Add(p[6]).MulScalar(0.5) + fe.V[14] = p[6].Add(p[7]).MulScalar(0.5) + fe.V[15] = p[7].Add(p[4]).MulScalar(0.5) + + fe.V[16] = p[0].Add(p[4]).MulScalar(0.5) + fe.V[17] = p[1].Add(p[5]).MulScalar(0.5) + fe.V[18] = p[2].Add(p[6]).MulScalar(0.5) + fe.V[19] = p[3].Add(p[7]).MulScalar(0.5) + result = append(result, &fe) } diff --git a/render/marchhex8.go b/render/marchhex8.go index 513a5bff0..4a3c92777 100644 --- a/render/marchhex8.go +++ b/render/marchhex8.go @@ -92,6 +92,10 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { V: [8]v3.Vec{}, Layer: layerZ, } + + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + fe.V[7] = p[7] fe.V[6] = p[6] fe.V[5] = p[5] From 0cb05bcc241d2202fd4681cfe39138ac8f02a8e5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 11 Mar 2023 15:36:32 +0330 Subject: [PATCH 169/775] Comment --- render/finiteelements/mesh/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 38d92df97..dda4b4800 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -35,7 +35,7 @@ type Inp struct { LayerStart int // Output `inp` file would exclude end layer. LayerEnd int - // Layers fixed to the 3D print floor i.e. bottom layers. + // Layers fixed to the 3D print floor i.e. bottom layers. The boundary conditions. LayersFixed []int // To write only required nodes to `inp` file. TempVBuff *buffer.VB From be5581a7f020c6601e64de9cf67780422a3c2a69 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 13:44:34 +0330 Subject: [PATCH 170/775] Relocate code --- render/finiteelements/mesh/inp.go | 10 ---------- render/finiteelements/mesh/mesh.go | 12 ++++++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index dda4b4800..61fd07238 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -9,16 +9,6 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -// A dynamic type for meshes of finite elements like MeshTet4, MeshHex8, MeshHex20, ... -type MeshFE interface { - NodesPerElement() int - layerCount() int - feCountOnLayer(l int) int - feVertices(l, i int) []v3.Vec -} - -//----------------------------------------------------------------------------- - // To write different types of finite elements as ABAQUS or CalculiX `inp` file. type Inp struct { // Finite elements mesh. diff --git a/render/finiteelements/mesh/mesh.go b/render/finiteelements/mesh/mesh.go index 2d01613c8..939feb5e1 100644 --- a/render/finiteelements/mesh/mesh.go +++ b/render/finiteelements/mesh/mesh.go @@ -1,3 +1,15 @@ // Provide convenient types & functions for meshes consisting of finite elements. // Like 4-node tetrahedra, 8-node and 20-node hexahedra. package mesh + +import v3 "github.com/deadsy/sdfx/vec/v3" + +// A dynamic type for meshes of finite elements like MeshTet4, MeshHex8, MeshHex20, ... +type MeshFE interface { + NodesPerElement() int + layerCount() int + feCountOnLayer(l int) int + feVertices(l, i int) []v3.Vec +} + +//----------------------------------------------------------------------------- From aabc0a66c7eb8f7c1ee6b58ba8389fcb03f181e3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 15:30:27 +0330 Subject: [PATCH 171/775] Fix bug of `hex20`: *ERROR in splitline: there should not be more than 16 entries in a line; --- render/finiteelements/mesh/inp.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 61fd07238..4edd933a3 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -227,7 +227,9 @@ func (inp *Inp) writeElements(f *os.File) error { } else if inp.Mesh.NodesPerElement() == 8 { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) } else if inp.Mesh.NodesPerElement() == 20 { - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1, ids[10]+1, ids[11]+1, ids[12]+1, ids[13]+1, ids[14]+1, ids[15]+1, ids[16]+1, ids[17]+1, ids[18]+1, ids[19]+1)) + // There should not be more than 16 entries in a line; + // That's why there is new line in the middle. + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\n%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1, ids[10]+1, ids[11]+1, ids[12]+1, ids[13]+1, ids[14]+1, ids[15]+1, ids[16]+1, ids[17]+1, ids[18]+1, ids[19]+1)) } if err != nil { From 957c4dcdf17b0e955c79618a499c84c3da18cc3c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 15:59:33 +0330 Subject: [PATCH 172/775] Comment --- render/finiteelements/mesh/inp.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 4edd933a3..9e80ed916 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -229,6 +229,8 @@ func (inp *Inp) writeElements(f *os.File) error { } else if inp.Mesh.NodesPerElement() == 20 { // There should not be more than 16 entries in a line; // That's why there is new line in the middle. + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\n%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1, ids[10]+1, ids[11]+1, ids[12]+1, ids[13]+1, ids[14]+1, ids[15]+1, ids[16]+1, ids[17]+1, ids[18]+1, ids[19]+1)) } From 22fc296a30b0c663b5d872a9017a3f071978fa0f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 16:18:54 +0330 Subject: [PATCH 173/775] Fastest solver? --- render/finiteelements/mesh/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 9e80ed916..68d38dc12 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -303,7 +303,7 @@ func (inp *Inp) writeFooter(f *os.File) error { // Write analysis - _, err = f.WriteString("*STEP\n*STATIC\n") + _, err = f.WriteString("*STEP\n*STATIC,SOLVER=PaStiX\n") if err != nil { return err } From 0cc3424ecc0bc533744e82f79e78c4551ed26ef3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 16:29:15 +0330 Subject: [PATCH 174/775] Use default `slow` solver. Revert "Fastest solver?" This reverts commit 22fc296a30b0c663b5d872a9017a3f071978fa0f. --- render/finiteelements/mesh/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 68d38dc12..9e80ed916 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -303,7 +303,7 @@ func (inp *Inp) writeFooter(f *os.File) error { // Write analysis - _, err = f.WriteString("*STEP\n*STATIC,SOLVER=PaStiX\n") + _, err = f.WriteString("*STEP\n*STATIC\n") if err != nil { return err } From fce14926ff36f356fb95744d87fd9b027204f5ef Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 17:00:39 +0330 Subject: [PATCH 175/775] Apply `golint` recommendations --- examples/finite_elements/main.go | 6 ++-- render/finiteelements/mesh/hex20.go | 43 +++++++++++++++-------------- render/finiteelements/mesh/hex8.go | 43 +++++++++++++++-------------- render/finiteelements/mesh/inp.go | 12 ++++---- render/finiteelements/mesh/mesh.go | 6 ++-- render/finiteelements/mesh/tet4.go | 43 +++++++++++++++-------------- 6 files changed, 79 insertions(+), 74 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 68f13ff38..2b80fe176 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -26,7 +26,7 @@ import ( // Written file can be used by ABAQUS or CalculiX. func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := mesh.NewMeshTet4(s, render.NewMarchingCubesFEUniform(resolution)) + m, _ := mesh.NewTet4(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 lyrEnd := 20 @@ -46,7 +46,7 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Written file can be used by ABAQUS or CalculiX. func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := mesh.NewMeshHex8(s, render.NewMarchingCubesFEUniform(resolution)) + m, _ := mesh.NewHex8(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 lyrEnd := 20 @@ -76,7 +76,7 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Written file can be used by ABAQUS or CalculiX. func hex20FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. - m, _ := mesh.NewMeshHex20(s, render.NewMarchingCubesFEUniform(resolution)) + m, _ := mesh.NewHex20(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 lyrEnd := 20 diff --git a/render/finiteelements/mesh/hex20.go b/render/finiteelements/mesh/hex20.go index 6b9ff45c7..078cf6c85 100644 --- a/render/finiteelements/mesh/hex20.go +++ b/render/finiteelements/mesh/hex20.go @@ -7,24 +7,24 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -// A mesh of 20-node hexahedra. +// Hex20 is a mesh of 20-node hexahedra. // A sophisticated data structure for mesh is required. // The repeated nodes would be removed. // The element connectivity would be created with unique nodes. -type MeshHex20 struct { +type Hex20 struct { // Index buffer. IBuff *buffer.IB // Vertex buffer. VBuff *buffer.VB } -// To get a new mesh and number of its layers along Z-axis. -func NewMeshHex20(s sdf.SDF3, r render.RenderFE) (*MeshHex20, int) { +// NewHex20 returns a new mesh and number of its layers along Z-axis. +func NewHex20(s sdf.SDF3, r render.RenderFE) (*Hex20, int) { fes := render.ToHex20(s, r) _, _, layerCountZ := r.LayerCounts(s) - m := newMeshHex20(layerCountZ) + m := newHex20(layerCountZ) // Fill out the mesh with finite elements. for _, fe := range fes { @@ -40,14 +40,15 @@ func NewMeshHex20(s sdf.SDF3, r render.RenderFE) (*MeshHex20, int) { return m, layerCountZ } -func newMeshHex20(layerCount int) *MeshHex20 { - return &MeshHex20{ +func newHex20(layerCount int) *Hex20 { + return &Hex20{ IBuff: buffer.NewIB(layerCount, 20), VBuff: buffer.NewVB(), } } -func (m *MeshHex20) NodesPerElement() int { +// NodesPerElement returns nodes per element. +func (m *Hex20) NodesPerElement() int { return 20 } @@ -55,7 +56,7 @@ func (m *MeshHex20) NodesPerElement() int { // Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshHex20) addFE(l int, nodes [20]v3.Vec) { +func (m *Hex20) addFE(l int, nodes [20]v3.Vec) { indices := [20]uint32{} for n := 0; n < 20; n++ { indices[n] = m.addVertex(nodes[n]) @@ -63,30 +64,30 @@ func (m *MeshHex20) addFE(l int, nodes [20]v3.Vec) { m.IBuff.AddFE(l, indices[:]) } -func (m *MeshHex20) addVertex(vert v3.Vec) uint32 { +func (m *Hex20) addVertex(vert v3.Vec) uint32 { return m.VBuff.Id(vert) } -func (m *MeshHex20) vertexCount() int { +func (m *Hex20) vertexCount() int { return m.VBuff.VertexCount() } -func (m *MeshHex20) vertex(i uint32) v3.Vec { +func (m *Hex20) vertex(i uint32) v3.Vec { return m.VBuff.Vertex(i) } // Number of layers along the Z axis. -func (m *MeshHex20) layerCount() int { +func (m *Hex20) layerCount() int { return m.IBuff.LayerCount() } // Number of finite elements on a layer. -func (m *MeshHex20) feCountOnLayer(l int) int { +func (m *Hex20) feCountOnLayer(l int) int { return m.IBuff.FECountOnLayer(l) } // Number of finite elements for all layers. -func (m *MeshHex20) feCount() int { +func (m *Hex20) feCount() int { return m.IBuff.FECount() } @@ -95,7 +96,7 @@ func (m *MeshHex20) feCount() int { // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex20) feIndicies(l, i int) []uint32 { +func (m *Hex20) feIndicies(l, i int) []uint32 { return m.IBuff.FEIndicies(l, i) } @@ -104,7 +105,7 @@ func (m *MeshHex20) feIndicies(l, i int) []uint32 { // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex20) feVertices(l, i int) []v3.Vec { +func (m *Hex20) feVertices(l, i int) []v3.Vec { indices := m.IBuff.FEIndicies(l, i) vertices := make([]v3.Vec, 20) for n := 0; n < 20; n++ { @@ -113,10 +114,10 @@ func (m *MeshHex20) feVertices(l, i int) []v3.Vec { return vertices } -// Write mesh to ABAQUS or CalculiX `inp` file. +// WriteInp saves mesh to ABAQUS or CalculiX `inp` file. // Units of measurement are mm,N,s,K. // Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *MeshHex20) WriteInp( +func (m *Hex20) WriteInp( path string, layersFixed []int, massDensity float32, @@ -126,12 +127,12 @@ func (m *MeshHex20) WriteInp( return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) } -// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +// WriteInpLayers saves specific layers of mesh to ABAQUS or CalculiX `inp` file. // Result would include start layer. // Result would exclude end layer. // Units of measurement are mm,N,s,K. // Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *MeshHex20) WriteInpLayers( +func (m *Hex20) WriteInpLayers( path string, layerStart, layerEnd int, layersFixed []int, diff --git a/render/finiteelements/mesh/hex8.go b/render/finiteelements/mesh/hex8.go index 7a0073eb6..5a2c7e12f 100644 --- a/render/finiteelements/mesh/hex8.go +++ b/render/finiteelements/mesh/hex8.go @@ -7,24 +7,24 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -// A mesh of 8-node hexahedra. +// Hex8 is a mesh of 8-node hexahedra. // A sophisticated data structure for mesh is required. // The repeated nodes would be removed. // The element connectivity would be created with unique nodes. -type MeshHex8 struct { +type Hex8 struct { // Index buffer. IBuff *buffer.IB // Vertex buffer. VBuff *buffer.VB } -// To get a new mesh and number of its layers along Z-axis. -func NewMeshHex8(s sdf.SDF3, r render.RenderFE) (*MeshHex8, int) { +// NewHex8 returns a new mesh and number of its layers along Z-axis. +func NewHex8(s sdf.SDF3, r render.RenderFE) (*Hex8, int) { fes := render.ToHex8(s, r) _, _, layerCountZ := r.LayerCounts(s) - m := newMeshHex8(layerCountZ) + m := newHex8(layerCountZ) // Fill out the mesh with finite elements. for _, fe := range fes { @@ -40,14 +40,15 @@ func NewMeshHex8(s sdf.SDF3, r render.RenderFE) (*MeshHex8, int) { return m, layerCountZ } -func newMeshHex8(layerCount int) *MeshHex8 { - return &MeshHex8{ +func newHex8(layerCount int) *Hex8 { + return &Hex8{ IBuff: buffer.NewIB(layerCount, 8), VBuff: buffer.NewVB(), } } -func (m *MeshHex8) NodesPerElement() int { +// NodesPerElement returns nodes per element. +func (m *Hex8) NodesPerElement() int { return 8 } @@ -55,7 +56,7 @@ func (m *MeshHex8) NodesPerElement() int { // Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshHex8) addFE(l int, nodes [8]v3.Vec) { +func (m *Hex8) addFE(l int, nodes [8]v3.Vec) { indices := [8]uint32{} for n := 0; n < 8; n++ { indices[n] = m.addVertex(nodes[n]) @@ -63,30 +64,30 @@ func (m *MeshHex8) addFE(l int, nodes [8]v3.Vec) { m.IBuff.AddFE(l, indices[:]) } -func (m *MeshHex8) addVertex(vert v3.Vec) uint32 { +func (m *Hex8) addVertex(vert v3.Vec) uint32 { return m.VBuff.Id(vert) } -func (m *MeshHex8) vertexCount() int { +func (m *Hex8) vertexCount() int { return m.VBuff.VertexCount() } -func (m *MeshHex8) vertex(i uint32) v3.Vec { +func (m *Hex8) vertex(i uint32) v3.Vec { return m.VBuff.Vertex(i) } // Number of layers along the Z axis. -func (m *MeshHex8) layerCount() int { +func (m *Hex8) layerCount() int { return m.IBuff.LayerCount() } // Number of finite elements on a layer. -func (m *MeshHex8) feCountOnLayer(l int) int { +func (m *Hex8) feCountOnLayer(l int) int { return m.IBuff.FECountOnLayer(l) } // Number of finite elements for all layers. -func (m *MeshHex8) feCount() int { +func (m *Hex8) feCount() int { return m.IBuff.FECount() } @@ -95,7 +96,7 @@ func (m *MeshHex8) feCount() int { // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex8) feIndicies(l, i int) []uint32 { +func (m *Hex8) feIndicies(l, i int) []uint32 { return m.IBuff.FEIndicies(l, i) } @@ -104,7 +105,7 @@ func (m *MeshHex8) feIndicies(l, i int) []uint32 { // FE index on layer is input. // FE index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshHex8) feVertices(l, i int) []v3.Vec { +func (m *Hex8) feVertices(l, i int) []v3.Vec { indices := m.IBuff.FEIndicies(l, i) vertices := make([]v3.Vec, 8) for n := 0; n < 8; n++ { @@ -113,10 +114,10 @@ func (m *MeshHex8) feVertices(l, i int) []v3.Vec { return vertices } -// Write mesh to ABAQUS or CalculiX `inp` file. +// WriteInp saves mesh to ABAQUS or CalculiX `inp` file. // Units of measurement are mm,N,s,K. // Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *MeshHex8) WriteInp( +func (m *Hex8) WriteInp( path string, layersFixed []int, massDensity float32, @@ -126,12 +127,12 @@ func (m *MeshHex8) WriteInp( return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) } -// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +// WriteInpLayers saves specific layers of mesh to ABAQUS or CalculiX `inp` file. // Result would include start layer. // Result would exclude end layer. // Units of measurement are mm,N,s,K. // Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *MeshHex8) WriteInpLayers( +func (m *Hex8) WriteInpLayers( path string, layerStart, layerEnd int, layersFixed []int, diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 9e80ed916..4f7321089 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -9,10 +9,10 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -// To write different types of finite elements as ABAQUS or CalculiX `inp` file. +// Inp writes different types of finite elements as ABAQUS or CalculiX `inp` file. type Inp struct { // Finite elements mesh. - Mesh MeshFE + Mesh FE // Output `inp` file path. Path string // For writing nodes to a separate file. @@ -35,8 +35,9 @@ type Inp struct { PoissonRatio float32 } +// NewInp sets up a new writer. func NewInp( - m MeshFE, + m FE, path string, layerStart, layerEnd int, layersFixed []int, @@ -58,6 +59,7 @@ func NewInp( } } +// Write starts writing to `inp` file. func (inp *Inp) Write() error { f, err := os.Create(inp.Path) if err != nil { @@ -152,7 +154,7 @@ func (inp *Inp) Write() error { } defer fBou.Close() - err = inp.WriteBoundary(fBou) + err = inp.writeBoundary(fBou) if err != nil { return err } @@ -244,7 +246,7 @@ func (inp *Inp) writeElements(f *os.File) error { return nil } -func (inp *Inp) WriteBoundary(f *os.File) error { +func (inp *Inp) writeBoundary(f *os.File) error { // Declare vars outside loop for efficiency. var err error nodes := make([]v3.Vec, 0, inp.Mesh.NodesPerElement()) diff --git a/render/finiteelements/mesh/mesh.go b/render/finiteelements/mesh/mesh.go index 939feb5e1..79ca85542 100644 --- a/render/finiteelements/mesh/mesh.go +++ b/render/finiteelements/mesh/mesh.go @@ -1,11 +1,11 @@ -// Provide convenient types & functions for meshes consisting of finite elements. +// Package mesh provides convenient types & functions for meshes consisting of finite elements. // Like 4-node tetrahedra, 8-node and 20-node hexahedra. package mesh import v3 "github.com/deadsy/sdfx/vec/v3" -// A dynamic type for meshes of finite elements like MeshTet4, MeshHex8, MeshHex20, ... -type MeshFE interface { +// FE is a dynamic type for meshes of finite elements like Tet4, Hex8, Hex20, ... +type FE interface { NodesPerElement() int layerCount() int feCountOnLayer(l int) int diff --git a/render/finiteelements/mesh/tet4.go b/render/finiteelements/mesh/tet4.go index 12522112e..f141f10cb 100644 --- a/render/finiteelements/mesh/tet4.go +++ b/render/finiteelements/mesh/tet4.go @@ -7,24 +7,24 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -// A mesh of 4-node tetrahedra. +// Tet4 is a mesh of 4-node tetrahedra. // A sophisticated data structure for mesh is required. // The repeated nodes would be removed. // The element connectivity would be created with unique nodes. -type MeshTet4 struct { +type Tet4 struct { // Index buffer. IBuff *buffer.IB // Vertex buffer. VBuff *buffer.VB } -// To get a new mesh and number of its layers along Z-axis. -func NewMeshTet4(s sdf.SDF3, r render.RenderFE) (*MeshTet4, int) { +// NewTet4 returns a new mesh and number of its layers along Z-axis. +func NewTet4(s sdf.SDF3, r render.RenderFE) (*Tet4, int) { fes := render.ToTet4(s, r) _, _, layerCountZ := r.LayerCounts(s) - m := newMeshTet4(layerCountZ) + m := newTet4(layerCountZ) // Fill out the mesh with finite elements. for _, fe := range fes { @@ -36,14 +36,15 @@ func NewMeshTet4(s sdf.SDF3, r render.RenderFE) (*MeshTet4, int) { return m, layerCountZ } -func newMeshTet4(layerCount int) *MeshTet4 { - return &MeshTet4{ +func newTet4(layerCount int) *Tet4 { + return &Tet4{ IBuff: buffer.NewIB(layerCount, 4), VBuff: buffer.NewVB(), } } -func (m *MeshTet4) NodesPerElement() int { +// NodesPerElement returns nodes per element. +func (m *Tet4) NodesPerElement() int { return 4 } @@ -51,7 +52,7 @@ func (m *MeshTet4) NodesPerElement() int { // Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (m *MeshTet4) addFE(l int, nodes [4]v3.Vec) { +func (m *Tet4) addFE(l int, nodes [4]v3.Vec) { indices := [4]uint32{} for n := 0; n < 4; n++ { indices[n] = m.addVertex(nodes[n]) @@ -59,30 +60,30 @@ func (m *MeshTet4) addFE(l int, nodes [4]v3.Vec) { m.IBuff.AddFE(l, indices[:]) } -func (m *MeshTet4) addVertex(vert v3.Vec) uint32 { +func (m *Tet4) addVertex(vert v3.Vec) uint32 { return m.VBuff.Id(vert) } -func (m *MeshTet4) vertexCount() int { +func (m *Tet4) vertexCount() int { return m.VBuff.VertexCount() } -func (m *MeshTet4) vertex(i uint32) v3.Vec { +func (m *Tet4) vertex(i uint32) v3.Vec { return m.VBuff.Vertex(i) } // Number of layers along the Z axis. -func (m *MeshTet4) layerCount() int { +func (m *Tet4) layerCount() int { return m.IBuff.LayerCount() } // Number of tetrahedra on a layer. -func (m *MeshTet4) feCountOnLayer(l int) int { +func (m *Tet4) feCountOnLayer(l int) int { return m.IBuff.FECountOnLayer(l) } // Number of tetrahedra for all layers. -func (m *MeshTet4) feCount() int { +func (m *Tet4) feCount() int { return m.IBuff.FECount() } @@ -91,7 +92,7 @@ func (m *MeshTet4) feCount() int { // Tetrahedron index on layer is input. // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) feIndicies(l, i int) []uint32 { +func (m *Tet4) feIndicies(l, i int) []uint32 { return m.IBuff.FEIndicies(l, i) } @@ -100,7 +101,7 @@ func (m *MeshTet4) feIndicies(l, i int) []uint32 { // Tetrahedron index on layer is input. // Tetrahedron index could be from 0 to number of tetrahedra on layer. // Don't return error to increase performance. -func (m *MeshTet4) feVertices(l, i int) []v3.Vec { +func (m *Tet4) feVertices(l, i int) []v3.Vec { indices := m.IBuff.FEIndicies(l, i) vertices := make([]v3.Vec, 4) for n := 0; n < 4; n++ { @@ -109,8 +110,8 @@ func (m *MeshTet4) feVertices(l, i int) []v3.Vec { return vertices } -// Write mesh to ABAQUS or CalculiX `inp` file. -func (m *MeshTet4) WriteInp( +// WriteInp writes mesh to ABAQUS or CalculiX `inp` file. +func (m *Tet4) WriteInp( path string, layersFixed []int, massDensity float32, @@ -120,10 +121,10 @@ func (m *MeshTet4) WriteInp( return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) } -// Write specific layers of mesh to ABAQUS or CalculiX `inp` file. +// WriteInpLayers writes specific layers of mesh to ABAQUS or CalculiX `inp` file. // Result would include start layer. // Result would exclude end layer. -func (m *MeshTet4) WriteInpLayers( +func (m *Tet4) WriteInpLayers( path string, layerStart, layerEnd int, layersFixed []int, From acd63f47e9e6d38062d5b9d9dacb089ac100efae Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 17:12:45 +0330 Subject: [PATCH 176/775] Simplify & comment --- render/finiteelements/mesh/hex20.go | 4 ++-- render/finiteelements/mesh/hex8.go | 4 ++-- render/finiteelements/mesh/inp.go | 34 ++++++++++++++--------------- render/finiteelements/mesh/mesh.go | 11 ++++++++-- render/finiteelements/mesh/tet4.go | 4 ++-- 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/render/finiteelements/mesh/hex20.go b/render/finiteelements/mesh/hex20.go index 078cf6c85..030c65db0 100644 --- a/render/finiteelements/mesh/hex20.go +++ b/render/finiteelements/mesh/hex20.go @@ -47,8 +47,8 @@ func newHex20(layerCount int) *Hex20 { } } -// NodesPerElement returns nodes per element. -func (m *Hex20) NodesPerElement() int { +// Npe returns number of nodes per element. +func (m *Hex20) Npe() int { return 20 } diff --git a/render/finiteelements/mesh/hex8.go b/render/finiteelements/mesh/hex8.go index 5a2c7e12f..62c9cc97f 100644 --- a/render/finiteelements/mesh/hex8.go +++ b/render/finiteelements/mesh/hex8.go @@ -47,8 +47,8 @@ func newHex8(layerCount int) *Hex8 { } } -// NodesPerElement returns nodes per element. -func (m *Hex8) NodesPerElement() int { +// Npe returns number of nodes per element. +func (m *Hex8) Npe() int { return 8 } diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 4f7321089..22193390e 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -103,11 +103,11 @@ func (inp *Inp) Write() error { // Write elements. ElementType := "" - if inp.Mesh.NodesPerElement() == 4 { + if inp.Mesh.Npe() == 4 { ElementType = "C3D4" - } else if inp.Mesh.NodesPerElement() == 8 { + } else if inp.Mesh.Npe() == 8 { ElementType = "C3D8" - } else if inp.Mesh.NodesPerElement() == 20 { + } else if inp.Mesh.Npe() == 20 { ElementType = "C3D20R" } @@ -185,18 +185,18 @@ func (inp *Inp) writeHeader(f *os.File) error { func (inp *Inp) writeNodes(f *os.File) error { // Declare vars outside loop for efficiency. var err error - nodes := make([]v3.Vec, 0, inp.Mesh.NodesPerElement()) - ids := make([]uint32, inp.Mesh.NodesPerElement()) + nodes := make([]v3.Vec, 0, inp.Mesh.Npe()) + ids := make([]uint32, inp.Mesh.Npe()) for l := inp.LayerStart; l < inp.LayerEnd; l++ { for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { // Get the node IDs. nodes = inp.Mesh.feVertices(l, i) - for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + for n := 0; n < inp.Mesh.Npe(); n++ { ids[n] = inp.TempVBuff.Id(nodes[n]) } // Write the node IDs. - for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + for n := 0; n < inp.Mesh.Npe(); n++ { // ID starts from one not zero. _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) if err != nil { @@ -212,23 +212,23 @@ func (inp *Inp) writeNodes(f *os.File) error { func (inp *Inp) writeElements(f *os.File) error { // Declare vars outside loop for efficiency. var err error - nodes := make([]v3.Vec, 0, inp.Mesh.NodesPerElement()) - ids := make([]uint32, inp.Mesh.NodesPerElement()) + nodes := make([]v3.Vec, 0, inp.Mesh.Npe()) + ids := make([]uint32, inp.Mesh.Npe()) var eleID uint32 for l := inp.LayerStart; l < inp.LayerEnd; l++ { for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { nodes = inp.Mesh.feVertices(l, i) - for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + for n := 0; n < inp.Mesh.Npe(); n++ { ids[n] = inp.TempVBuff.Id(nodes[n]) } // ID starts from one not zero. - if inp.Mesh.NodesPerElement() == 4 { + if inp.Mesh.Npe() == 4 { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1)) - } else if inp.Mesh.NodesPerElement() == 8 { + } else if inp.Mesh.Npe() == 8 { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) - } else if inp.Mesh.NodesPerElement() == 20 { + } else if inp.Mesh.Npe() == 20 { // There should not be more than 16 entries in a line; // That's why there is new line in the middle. // Refer to CalculiX solver documentation: @@ -249,17 +249,17 @@ func (inp *Inp) writeElements(f *os.File) error { func (inp *Inp) writeBoundary(f *os.File) error { // Declare vars outside loop for efficiency. var err error - nodes := make([]v3.Vec, 0, inp.Mesh.NodesPerElement()) - ids := make([]uint32, inp.Mesh.NodesPerElement()) + nodes := make([]v3.Vec, 0, inp.Mesh.Npe()) + ids := make([]uint32, inp.Mesh.Npe()) for l := range inp.LayersFixed { for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { nodes = inp.Mesh.feVertices(l, i) - for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + for n := 0; n < inp.Mesh.Npe(); n++ { ids[n] = inp.TempVBuff.Id(nodes[n]) } // Write the node IDs. - for n := 0; n < inp.Mesh.NodesPerElement(); n++ { + for n := 0; n < inp.Mesh.Npe(); n++ { // ID starts from one not zero. _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) if err != nil { diff --git a/render/finiteelements/mesh/mesh.go b/render/finiteelements/mesh/mesh.go index 79ca85542..7bd0beaae 100644 --- a/render/finiteelements/mesh/mesh.go +++ b/render/finiteelements/mesh/mesh.go @@ -4,11 +4,18 @@ package mesh import v3 "github.com/deadsy/sdfx/vec/v3" -// FE is a dynamic type for meshes of finite elements like Tet4, Hex8, Hex20, ... +// FE is a dynamic type for a mesh of finite elements like Tet4, Hex8, Hex20, ... type FE interface { - NodesPerElement() int + // Number of nodes per element. + Npe() int + // Number of layers along the Z axis. layerCount() int + // Number of finite elements on a layer. feCountOnLayer(l int) int + // Get a finite element. + // FE vertices are returned. + // Layer index is input. + // FE index on layer is input. feVertices(l, i int) []v3.Vec } diff --git a/render/finiteelements/mesh/tet4.go b/render/finiteelements/mesh/tet4.go index f141f10cb..373aa1f44 100644 --- a/render/finiteelements/mesh/tet4.go +++ b/render/finiteelements/mesh/tet4.go @@ -43,8 +43,8 @@ func newTet4(layerCount int) *Tet4 { } } -// NodesPerElement returns nodes per element. -func (m *Tet4) NodesPerElement() int { +// Npe returns number of nodes per element. +func (m *Tet4) Npe() int { return 4 } From 7c75971290f81147f96f6d84e7dc8f9c21171b12 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 17:38:44 +0330 Subject: [PATCH 177/775] Log about Tet4: not finished yet --- examples/finite_elements/main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 2b80fe176..e8888304f 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -10,6 +10,7 @@ Output `inp` file is consumable by ABAQUS or CalculiX. package main import ( + "fmt" "log" "os" @@ -36,6 +37,9 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { if err != nil { return err } + + fmt.Println("tet4 FE is not implemented, there is TODO in function mcToTet4") + return nil } From 8fff3f1989d4baa2f5d92f7933db4e6ebd140388 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 17:59:09 +0330 Subject: [PATCH 178/775] Change log --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index e8888304f..973b3a6d8 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -38,7 +38,7 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { return err } - fmt.Println("tet4 FE is not implemented, there is TODO in function mcToTet4") + fmt.Println("Tet4 FE is not implemented, there is TODO in function mcToTet4") return nil } From f931a83dd2bf4589fd0d436d0572c30feb7a9e8c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 12 Mar 2023 18:01:18 +0330 Subject: [PATCH 179/775] Comment --- render/finiteelements/buffer/buffer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/buffer.go b/render/finiteelements/buffer/buffer.go index 30b3e0994..5a11ed477 100644 --- a/render/finiteelements/buffer/buffer.go +++ b/render/finiteelements/buffer/buffer.go @@ -1,2 +1,2 @@ -// Index and vertex buffers +// Package buffer implements index and vertex buffers for finite element mesh. package buffer From e765cc250052bd5b5be05192d37e454b8c6e4144 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 13 Mar 2023 10:27:12 +0330 Subject: [PATCH 180/775] README: CCX solver options --- examples/finite_elements/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 151f3f0bd..05449c95f 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -46,3 +46,7 @@ The boundary conditions and loads used in the calculation will be available toge ```bash cgx teapot-hex8.frd teapot-hex8.inp ``` + +## Math solver + +The default CCX math solver is `SPOOLES` which is slow. Apparently `PARDISO` is faster and `PaStiX` is the fastest. But it's needed to build the CCX with `PARDISO` or `PaStiX` math libraries. From 8ae13ce76341a1b5fe3dc61783e17f3920682474 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 12:06:40 +0330 Subject: [PATCH 181/775] New file for Octree FE --- render/marchfex.go | 110 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 render/marchfex.go diff --git a/render/marchfex.go b/render/marchfex.go new file mode 100644 index 000000000..4056b326a --- /dev/null +++ b/render/marchfex.go @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------------- +/* + +Marching Cubes Octree + +Convert an SDF3 to finite elements. +Uses octree space subdivision. + +*/ +//----------------------------------------------------------------------------- + +package render + +import ( + "fmt" + "math" + + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" +) + +//----------------------------------------------------------------------------- + +// Process a cube. Generate finite elements, or more cubes. +func (dc *dcache3) processCubeHex8(c *cube, output chan<- []*Triangle3) { + if !dc.isEmpty(c) { + if c.n == 1 { + // this cube is at the required resolution + c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) + c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) + c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) + c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) + c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) + c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) + c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) + c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) + corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} + values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} + // output the triangle(s) for this cube + output <- mcToTriangles(corners, values, 0) + } else { + // process the sub cubes + n := c.n - 1 + s := 1 << n + // TODO - turn these into throttled go-routines + dc.processCube(&cube{c.v.Add(v3i.Vec{0, 0, 0}), n}, output) + dc.processCube(&cube{c.v.Add(v3i.Vec{s, 0, 0}), n}, output) + dc.processCube(&cube{c.v.Add(v3i.Vec{s, s, 0}), n}, output) + dc.processCube(&cube{c.v.Add(v3i.Vec{0, s, 0}), n}, output) + dc.processCube(&cube{c.v.Add(v3i.Vec{0, 0, s}), n}, output) + dc.processCube(&cube{c.v.Add(v3i.Vec{s, 0, s}), n}, output) + dc.processCube(&cube{c.v.Add(v3i.Vec{s, s, s}), n}, output) + dc.processCube(&cube{c.v.Add(v3i.Vec{0, s, s}), n}, output) + } + } +} + +//----------------------------------------------------------------------------- + +// marchingCubesFEOctree generates a triangle mesh for an SDF3 using octree subdivision. +func marchingCubesFEOctree(s sdf.SDF3, resolution float64, output chan<- []*Triangle3) { + // Scale the bounding box about the center to make sure the boundaries + // aren't on the object surface. + bb := s.BoundingBox() + bb = bb.ScaleAboutCenter(1.01) + longAxis := bb.Size().MaxComponent() + // We want to test the smallest cube (side == resolution) for emptiness + // so the level = 0 cube is at half resolution. + resolution = 0.5 * resolution + // how many cube levels for the octree? + levels := uint(math.Ceil(math.Log2(longAxis/resolution))) + 1 + // create the distance cache + dc := newDcache3(s, bb.Min, resolution, levels) + // process the octree, start at the top level + dc.processCubeHex8(&cube{v3i.Vec{0, 0, 0}, levels - 1}, output) +} + +//----------------------------------------------------------------------------- + +// MarchingCubesFEOctree renders using marching cubes with octree space sampling. +type MarchingCubesFEOctree struct { + meshCells int // number of cells on the longest axis of bounding box. e.g 200 +} + +// NewMarchingCubesFEOctree returns a Render3 object. +func NewMarchingCubesFEOctree(meshCells int) *MarchingCubesFEOctree { + return &MarchingCubesFEOctree{ + meshCells: meshCells, + } +} + +// Info returns a string describing the rendered volume. +func (r *MarchingCubesFEOctree) Info(s sdf.SDF3) string { + bbSize := s.BoundingBox().Size() + resolution := bbSize.MaxComponent() / float64(r.meshCells) + cells := conv.V3ToV3i(bbSize.MulScalar(1 / resolution)) + return fmt.Sprintf("%dx%dx%d, resolution %.2f", cells.X, cells.Y, cells.Z, resolution) +} + +// Render produces a 3d triangle mesh over the bounding volume of an sdf3. +func (r *MarchingCubesFEOctree) Render(s sdf.SDF3, output chan<- []*Triangle3) { + // work out the sampling resolution to use + bbSize := s.BoundingBox().Size() + resolution := bbSize.MaxComponent() / float64(r.meshCells) + marchingCubesFEOctree(s, resolution, output) +} + +//----------------------------------------------------------------------------- From ee8e9a293968f1e5acddc09f83e0148dfe3b32a3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 12:26:55 +0330 Subject: [PATCH 182/775] Rename to simplify --- examples/finite_elements/main.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 973b3a6d8..8735991cc 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -25,7 +25,7 @@ import ( // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. -func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { +func tet4(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := mesh.NewTet4(s, render.NewMarchingCubesFEUniform(resolution)) @@ -48,7 +48,7 @@ func tet4FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. -func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { +func hex8(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := mesh.NewHex8(s, render.NewMarchingCubesFEUniform(resolution)) @@ -78,7 +78,7 @@ func hex8FiniteElements(s sdf.SDF3, resolution int, pth string) error { // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. -func hex20FiniteElements(s sdf.SDF3, resolution int, pth string) error { +func hex20(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := mesh.NewHex20(s, render.NewMarchingCubesFEUniform(resolution)) @@ -118,17 +118,17 @@ func main() { log.Fatalf("error: %s", err) } - err = tet4FiniteElements(teapotSdf, 80, "teapot-tet4.inp") + err = tet4(teapotSdf, 80, "teapot-tet4.inp") if err != nil { log.Fatalf("error: %s", err) } - err = hex8FiniteElements(teapotSdf, 80, "teapot-hex8.inp") + err = hex8(teapotSdf, 80, "teapot-hex8.inp") if err != nil { log.Fatalf("error: %s", err) } - err = hex20FiniteElements(teapotSdf, 80, "teapot-hex20.inp") + err = hex20(teapotSdf, 80, "teapot-hex20.inp") if err != nil { log.Fatalf("error: %s", err) } From 1ea742ff96fcfc850f4db14fb24a416fe8b22222 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 12:28:03 +0330 Subject: [PATCH 183/775] Comments --- examples/finite_elements/main.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 8735991cc..0daac2646 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -21,10 +21,6 @@ import ( ) // 4-node tetrahedral elements. -// -// Render SDF3 to finite elements. -// Write finite elements to an `inp` file. -// Written file can be used by ABAQUS or CalculiX. func tet4(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := mesh.NewTet4(s, render.NewMarchingCubesFEUniform(resolution)) @@ -44,10 +40,6 @@ func tet4(s sdf.SDF3, resolution int, pth string) error { } // 8-node hexahedral elements. -// -// Render SDF3 to finite elements. -// Write finite elements to an `inp` file. -// Written file can be used by ABAQUS or CalculiX. func hex8(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := mesh.NewHex8(s, render.NewMarchingCubesFEUniform(resolution)) @@ -74,10 +66,6 @@ func hex8(s sdf.SDF3, resolution int, pth string) error { } // 20-node hexahedral elements. -// -// Render SDF3 to finite elements. -// Write finite elements to an `inp` file. -// Written file can be used by ABAQUS or CalculiX. func hex20(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := mesh.NewHex20(s, render.NewMarchingCubesFEUniform(resolution)) @@ -103,6 +91,9 @@ func hex20(s sdf.SDF3, resolution int, pth string) error { return nil } +// Render SDF3 to finite elements. +// Write finite elements to an `inp` file. +// Written file can be used by ABAQUS or CalculiX. func main() { stl := "../../files/teapot.stl" From 04186160caae235c2d7e71a39e5dba184cb65b95 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 12:49:43 +0330 Subject: [PATCH 184/775] New interface funcs --- examples/finite_elements/main.go | 27 +++++++++++++++++++++++++++ render/marchfex.go | 27 ++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 0daac2646..3e6dc9b92 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -91,6 +91,33 @@ func hex20(s sdf.SDF3, resolution int, pth string) error { return nil } +// 8-node hexahedral elements. +// With adaptive mesh refinement. +func hex8adaptive(s sdf.SDF3, resolution int, pth string) error { + // Create a mesh out of finite elements. + m, _ := mesh.NewHex8(s, render.NewMarchingCubesFEOctree(resolution)) + + lyrStart := 0 + lyrEnd := 20 + + // Write just some layers of mesh to a file. + // + // Units are mm,N,sec. + // Force per area = N/mm2 or MPa + // Mass density = Ns2/mm4 + // Refer to the "Units" chapter of: + // http://www.dhondt.de/ccx_2.20.pdf + // + // Mechanical properties are based on typical SLA resins. + // + // TODO: Correct resin specifications. + err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + if err != nil { + return err + } + return nil +} + // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. diff --git a/render/marchfex.go b/render/marchfex.go index 4056b326a..8222e6848 100644 --- a/render/marchfex.go +++ b/render/marchfex.go @@ -99,8 +99,33 @@ func (r *MarchingCubesFEOctree) Info(s sdf.SDF3) string { return fmt.Sprintf("%dx%dx%d, resolution %.2f", cells.X, cells.Y, cells.Z, resolution) } +// LayerCounts computes number of layes in X, Y, Z directions. +// We are specifically interested in Z direction. +func (r *MarchingCubesFEOctree) LayerCounts(s sdf.SDF3) (int, int, int) { + bbSize := s.BoundingBox().Size() + resolution := bbSize.MaxComponent() / float64(r.meshCells) + cells := conv.V3ToV3i(bbSize.MulScalar(1 / resolution)) + return cells.X, cells.Y, cells.Z +} + +// Render produces a 3d triangle mesh over the bounding volume of an sdf3. +func (r *MarchingCubesFEOctree) RenderTet4(s sdf.SDF3, output chan<- []*Tet4) { + // work out the sampling resolution to use + bbSize := s.BoundingBox().Size() + resolution := bbSize.MaxComponent() / float64(r.meshCells) + marchingCubesFEOctree(s, resolution, output) +} + +// Render produces a 3d triangle mesh over the bounding volume of an sdf3. +func (r *MarchingCubesFEOctree) RenderHex8(s sdf.SDF3, output chan<- []*Hex8) { + // work out the sampling resolution to use + bbSize := s.BoundingBox().Size() + resolution := bbSize.MaxComponent() / float64(r.meshCells) + marchingCubesFEOctree(s, resolution, output) +} + // Render produces a 3d triangle mesh over the bounding volume of an sdf3. -func (r *MarchingCubesFEOctree) Render(s sdf.SDF3, output chan<- []*Triangle3) { +func (r *MarchingCubesFEOctree) RenderHex20(s sdf.SDF3, output chan<- []*Hex20) { // work out the sampling resolution to use bbSize := s.BoundingBox().Size() resolution := bbSize.MaxComponent() / float64(r.meshCells) From 0d70bb6693523b431b079e8bfa3b777c879788a5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 13:11:34 +0330 Subject: [PATCH 185/775] New funcs & files for Octree --- render/marchfex.go | 72 ++++++++++++++++------------------------- render/marchfexhex20.go | 42 ++++++++++++++++++++++++ render/marchfexhex8.go | 42 ++++++++++++++++++++++++ render/marchfextet4.go | 42 ++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 45 deletions(-) create mode 100644 render/marchfexhex20.go create mode 100644 render/marchfexhex8.go create mode 100644 render/marchfextet4.go diff --git a/render/marchfex.go b/render/marchfex.go index 8222e6848..6dc9d5371 100644 --- a/render/marchfex.go +++ b/render/marchfex.go @@ -17,50 +17,12 @@ import ( "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" - v3 "github.com/deadsy/sdfx/vec/v3" "github.com/deadsy/sdfx/vec/v3i" ) //----------------------------------------------------------------------------- -// Process a cube. Generate finite elements, or more cubes. -func (dc *dcache3) processCubeHex8(c *cube, output chan<- []*Triangle3) { - if !dc.isEmpty(c) { - if c.n == 1 { - // this cube is at the required resolution - c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) - c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) - c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) - c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) - c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) - c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) - c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) - c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) - corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} - values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} - // output the triangle(s) for this cube - output <- mcToTriangles(corners, values, 0) - } else { - // process the sub cubes - n := c.n - 1 - s := 1 << n - // TODO - turn these into throttled go-routines - dc.processCube(&cube{c.v.Add(v3i.Vec{0, 0, 0}), n}, output) - dc.processCube(&cube{c.v.Add(v3i.Vec{s, 0, 0}), n}, output) - dc.processCube(&cube{c.v.Add(v3i.Vec{s, s, 0}), n}, output) - dc.processCube(&cube{c.v.Add(v3i.Vec{0, s, 0}), n}, output) - dc.processCube(&cube{c.v.Add(v3i.Vec{0, 0, s}), n}, output) - dc.processCube(&cube{c.v.Add(v3i.Vec{s, 0, s}), n}, output) - dc.processCube(&cube{c.v.Add(v3i.Vec{s, s, s}), n}, output) - dc.processCube(&cube{c.v.Add(v3i.Vec{0, s, s}), n}, output) - } - } -} - -//----------------------------------------------------------------------------- - -// marchingCubesFEOctree generates a triangle mesh for an SDF3 using octree subdivision. -func marchingCubesFEOctree(s sdf.SDF3, resolution float64, output chan<- []*Triangle3) { +func distanceCache(s sdf.SDF3, resolution float64) (*dcache3, uint) { // Scale the bounding box about the center to make sure the boundaries // aren't on the object surface. bb := s.BoundingBox() @@ -73,10 +35,30 @@ func marchingCubesFEOctree(s sdf.SDF3, resolution float64, output chan<- []*Tria levels := uint(math.Ceil(math.Log2(longAxis/resolution))) + 1 // create the distance cache dc := newDcache3(s, bb.Min, resolution, levels) + return dc, levels +} + +// marchingCubesTet4Octree generates finite elements for an SDF3 using octree subdivision. +func marchingCubesTet4Octree(s sdf.SDF3, resolution float64, output chan<- []*Tet4) { + dc, levels := distanceCache(s, resolution) + // process the octree, start at the top level + dc.processCubeTet4(&cube{v3i.Vec{0, 0, 0}, levels - 1}, output) +} + +// marchingCubesHex8Octree generates finite elements for an SDF3 using octree subdivision. +func marchingCubesHex8Octree(s sdf.SDF3, resolution float64, output chan<- []*Hex8) { + dc, levels := distanceCache(s, resolution) // process the octree, start at the top level dc.processCubeHex8(&cube{v3i.Vec{0, 0, 0}, levels - 1}, output) } +// marchingCubesHex20Octree generates finite elements for an SDF3 using octree subdivision. +func marchingCubesHex20Octree(s sdf.SDF3, resolution float64, output chan<- []*Hex20) { + dc, levels := distanceCache(s, resolution) + // process the octree, start at the top level + dc.processCubeHex20(&cube{v3i.Vec{0, 0, 0}, levels - 1}, output) +} + //----------------------------------------------------------------------------- // MarchingCubesFEOctree renders using marching cubes with octree space sampling. @@ -108,28 +90,28 @@ func (r *MarchingCubesFEOctree) LayerCounts(s sdf.SDF3) (int, int, int) { return cells.X, cells.Y, cells.Z } -// Render produces a 3d triangle mesh over the bounding volume of an sdf3. +// RenderTet4 produces finite elements over the bounding volume of an sdf3. func (r *MarchingCubesFEOctree) RenderTet4(s sdf.SDF3, output chan<- []*Tet4) { // work out the sampling resolution to use bbSize := s.BoundingBox().Size() resolution := bbSize.MaxComponent() / float64(r.meshCells) - marchingCubesFEOctree(s, resolution, output) + marchingCubesTet4Octree(s, resolution, output) } -// Render produces a 3d triangle mesh over the bounding volume of an sdf3. +// RenderHex8 produces finite elements over the bounding volume of an sdf3. func (r *MarchingCubesFEOctree) RenderHex8(s sdf.SDF3, output chan<- []*Hex8) { // work out the sampling resolution to use bbSize := s.BoundingBox().Size() resolution := bbSize.MaxComponent() / float64(r.meshCells) - marchingCubesFEOctree(s, resolution, output) + marchingCubesHex8Octree(s, resolution, output) } -// Render produces a 3d triangle mesh over the bounding volume of an sdf3. +// RenderHex20 produces finite elements over the bounding volume of an sdf3. func (r *MarchingCubesFEOctree) RenderHex20(s sdf.SDF3, output chan<- []*Hex20) { // work out the sampling resolution to use bbSize := s.BoundingBox().Size() resolution := bbSize.MaxComponent() / float64(r.meshCells) - marchingCubesFEOctree(s, resolution, output) + marchingCubesHex20Octree(s, resolution, output) } //----------------------------------------------------------------------------- diff --git a/render/marchfexhex20.go b/render/marchfexhex20.go new file mode 100644 index 000000000..b88ae316b --- /dev/null +++ b/render/marchfexhex20.go @@ -0,0 +1,42 @@ +package render + +import ( + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" +) + +//----------------------------------------------------------------------------- + +// Process a cube. Generate finite elements, or more cubes. +func (dc *dcache3) processCubeHex20(c *cube, output chan<- []*Hex20) { + if !dc.isEmpty(c) { + if c.n == 1 { + // this cube is at the required resolution + c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) + c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) + c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) + c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) + c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) + c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) + c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) + c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) + corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} + values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} + // output the triangle(s) for this cube + output <- mcToHex20(corners, values, 0, -1) + } else { + // process the sub cubes + n := c.n - 1 + s := 1 << n + // TODO - turn these into throttled go-routines + dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{0, 0, 0}), n}, output) + dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{s, 0, 0}), n}, output) + dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{s, s, 0}), n}, output) + dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{0, s, 0}), n}, output) + dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{0, 0, s}), n}, output) + dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{s, 0, s}), n}, output) + dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{s, s, s}), n}, output) + dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{0, s, s}), n}, output) + } + } +} diff --git a/render/marchfexhex8.go b/render/marchfexhex8.go new file mode 100644 index 000000000..90e417445 --- /dev/null +++ b/render/marchfexhex8.go @@ -0,0 +1,42 @@ +package render + +import ( + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" +) + +//----------------------------------------------------------------------------- + +// Process a cube. Generate finite elements, or more cubes. +func (dc *dcache3) processCubeHex8(c *cube, output chan<- []*Hex8) { + if !dc.isEmpty(c) { + if c.n == 1 { + // this cube is at the required resolution + c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) + c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) + c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) + c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) + c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) + c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) + c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) + c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) + corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} + values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} + // output the triangle(s) for this cube + output <- mcToHex8(corners, values, 0, -1) + } else { + // process the sub cubes + n := c.n - 1 + s := 1 << n + // TODO - turn these into throttled go-routines + dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{0, 0, 0}), n}, output) + dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{s, 0, 0}), n}, output) + dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{s, s, 0}), n}, output) + dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{0, s, 0}), n}, output) + dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{0, 0, s}), n}, output) + dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{s, 0, s}), n}, output) + dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{s, s, s}), n}, output) + dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{0, s, s}), n}, output) + } + } +} diff --git a/render/marchfextet4.go b/render/marchfextet4.go new file mode 100644 index 000000000..876fd135f --- /dev/null +++ b/render/marchfextet4.go @@ -0,0 +1,42 @@ +package render + +import ( + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" +) + +//----------------------------------------------------------------------------- + +// Process a cube. Generate finite elements, or more cubes. +func (dc *dcache3) processCubeTet4(c *cube, output chan<- []*Tet4) { + if !dc.isEmpty(c) { + if c.n == 1 { + // this cube is at the required resolution + c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) + c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) + c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) + c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) + c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) + c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) + c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) + c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) + corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} + values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} + // output the triangle(s) for this cube + output <- mcToTet4(corners, values, 0, -1) + } else { + // process the sub cubes + n := c.n - 1 + s := 1 << n + // TODO - turn these into throttled go-routines + dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{0, 0, 0}), n}, output) + dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{s, 0, 0}), n}, output) + dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{s, s, 0}), n}, output) + dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{0, s, 0}), n}, output) + dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{0, 0, s}), n}, output) + dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{s, 0, s}), n}, output) + dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{s, s, s}), n}, output) + dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{0, s, s}), n}, output) + } + } +} From c25cb9c5fd6d523f58ec7008c172b9a7119afaf1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 13:13:57 +0330 Subject: [PATCH 186/775] Rename files --- render/{marchhex20.go => marchfehex20.go} | 0 render/{marchhex8.go => marchfehex8.go} | 0 render/{marchtet4.go => marchfetet4.go} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename render/{marchhex20.go => marchfehex20.go} (100%) rename render/{marchhex8.go => marchfehex8.go} (100%) rename render/{marchtet4.go => marchfetet4.go} (100%) diff --git a/render/marchhex20.go b/render/marchfehex20.go similarity index 100% rename from render/marchhex20.go rename to render/marchfehex20.go diff --git a/render/marchhex8.go b/render/marchfehex8.go similarity index 100% rename from render/marchhex8.go rename to render/marchfehex8.go diff --git a/render/marchtet4.go b/render/marchfetet4.go similarity index 100% rename from render/marchtet4.go rename to render/marchfetet4.go From 1d2f972437a316ecb52d5fa822c6bd3c90235072 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 13:19:19 +0330 Subject: [PATCH 187/775] Rename files: try to be more consistent --- render/{marchfe.go => march3fe.go} | 0 render/{marchfehex20.go => march3fehex20.go} | 0 render/{marchfehex8.go => march3fehex8.go} | 0 render/{marchfetet4.go => march3fetet4.go} | 0 render/{marchfex.go => march3xfe.go} | 0 render/{marchfexhex20.go => march3xfehex20.go} | 0 render/{marchfexhex8.go => march3xfehex8.go} | 0 render/{marchfextet4.go => march3xfetet4.go} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename render/{marchfe.go => march3fe.go} (100%) rename render/{marchfehex20.go => march3fehex20.go} (100%) rename render/{marchfehex8.go => march3fehex8.go} (100%) rename render/{marchfetet4.go => march3fetet4.go} (100%) rename render/{marchfex.go => march3xfe.go} (100%) rename render/{marchfexhex20.go => march3xfehex20.go} (100%) rename render/{marchfexhex8.go => march3xfehex8.go} (100%) rename render/{marchfextet4.go => march3xfetet4.go} (100%) diff --git a/render/marchfe.go b/render/march3fe.go similarity index 100% rename from render/marchfe.go rename to render/march3fe.go diff --git a/render/marchfehex20.go b/render/march3fehex20.go similarity index 100% rename from render/marchfehex20.go rename to render/march3fehex20.go diff --git a/render/marchfehex8.go b/render/march3fehex8.go similarity index 100% rename from render/marchfehex8.go rename to render/march3fehex8.go diff --git a/render/marchfetet4.go b/render/march3fetet4.go similarity index 100% rename from render/marchfetet4.go rename to render/march3fetet4.go diff --git a/render/marchfex.go b/render/march3xfe.go similarity index 100% rename from render/marchfex.go rename to render/march3xfe.go diff --git a/render/marchfexhex20.go b/render/march3xfehex20.go similarity index 100% rename from render/marchfexhex20.go rename to render/march3xfehex20.go diff --git a/render/marchfexhex8.go b/render/march3xfehex8.go similarity index 100% rename from render/marchfexhex8.go rename to render/march3xfehex8.go diff --git a/render/marchfextet4.go b/render/march3xfetet4.go similarity index 100% rename from render/marchfextet4.go rename to render/march3xfetet4.go From abd01e67230337d2fa1591b7cb1cb81956f7b0b4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 13:23:22 +0330 Subject: [PATCH 188/775] Call adaptive example --- examples/finite_elements/main.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 3e6dc9b92..67967afc7 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -100,17 +100,6 @@ func hex8adaptive(s sdf.SDF3, resolution int, pth string) error { lyrStart := 0 lyrEnd := 20 - // Write just some layers of mesh to a file. - // - // Units are mm,N,sec. - // Force per area = N/mm2 or MPa - // Mass density = Ns2/mm4 - // Refer to the "Units" chapter of: - // http://www.dhondt.de/ccx_2.20.pdf - // - // Mechanical properties are based on typical SLA resins. - // - // TODO: Correct resin specifications. err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) if err != nil { return err @@ -150,4 +139,9 @@ func main() { if err != nil { log.Fatalf("error: %s", err) } + + err = hex8adaptive(teapotSdf, 80, "teapot-hex20-adaptive.inp") + if err != nil { + log.Fatalf("error: %s", err) + } } From 92a0a9b7cfd9fae71663cb077f84bc167cd60228 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 14:05:51 +0330 Subject: [PATCH 189/775] Save all FE to 1st layer --- examples/finite_elements/main.go | 5 +---- render/march3xfehex8.go | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 67967afc7..ed417c3b3 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -97,10 +97,7 @@ func hex8adaptive(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. m, _ := mesh.NewHex8(s, render.NewMarchingCubesFEOctree(resolution)) - lyrStart := 0 - lyrEnd := 20 - - err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + err := m.WriteInp(pth, []int{0}, 1.25e-9, 900, 0.3) if err != nil { return err } diff --git a/render/march3xfehex8.go b/render/march3xfehex8.go index 90e417445..4dc652699 100644 --- a/render/march3xfehex8.go +++ b/render/march3xfehex8.go @@ -23,7 +23,7 @@ func (dc *dcache3) processCubeHex8(c *cube, output chan<- []*Hex8) { corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} // output the triangle(s) for this cube - output <- mcToHex8(corners, values, 0, -1) + output <- mcToHex8(corners, values, 0, 0) } else { // process the sub cubes n := c.n - 1 From 61191ae07f739403ad13cef0b58de16176258140 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 15 Mar 2023 14:21:46 +0330 Subject: [PATCH 190/775] Logic to save FE if all 8 values are non-positive --- render/march3xfehex8.go | 54 ++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/render/march3xfehex8.go b/render/march3xfehex8.go index 4dc652699..209736295 100644 --- a/render/march3xfehex8.go +++ b/render/march3xfehex8.go @@ -10,20 +10,50 @@ import ( // Process a cube. Generate finite elements, or more cubes. func (dc *dcache3) processCubeHex8(c *cube, output chan<- []*Hex8) { if !dc.isEmpty(c) { + + c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) + c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) + c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) + c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) + c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) + c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) + c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) + c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) + corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} + values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} + + anyPositive := false + for i := 0; i < 8; i++ { + if values[i] > 0 { + anyPositive = true + break + } + } + + if !anyPositive { + fe := Hex8{ + V: [8]v3.Vec{}, + Layer: 0, + } + + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + + fe.V[7] = corners[7] + fe.V[6] = corners[6] + fe.V[5] = corners[5] + fe.V[4] = corners[4] + fe.V[3] = corners[3] + fe.V[2] = corners[2] + fe.V[1] = corners[1] + fe.V[0] = corners[0] + + // output the finite element(s) for this cube + output <- []*Hex8{&fe} + } + if c.n == 1 { // this cube is at the required resolution - c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) - c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) - c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) - c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) - c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) - c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) - c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) - c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) - corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} - values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} - // output the triangle(s) for this cube - output <- mcToHex8(corners, values, 0, 0) } else { // process the sub cubes n := c.n - 1 From 0bcf81d8f1baf786d84f35a3d9c0bd1404743bd5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 15 May 2023 20:06:44 +0330 Subject: [PATCH 191/775] Comment: case index --- render/march3.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/render/march3.go b/render/march3.go index f2d46fc57..1f38eb307 100644 --- a/render/march3.go +++ b/render/march3.go @@ -359,12 +359,19 @@ var mcEdgeTable = [256]int{ // specify the edges used to create the triangle(s) var mcTriangleTable = [256][]int{ + // Case 0 {}, + // Case 2 {0, 8, 3}, + // Case 3 {0, 1, 9}, + // Case 4 {1, 8, 3, 9, 8, 1}, + // Case 5 {1, 2, 10}, + // Case 6 {0, 8, 3, 1, 2, 10}, + // Case 7 {9, 2, 10, 0, 2, 9}, {2, 8, 3, 2, 10, 8, 10, 9, 8}, {3, 11, 2}, From 8530c299158b99bbd2bcfcad50ee9f3c09da19f2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 15 May 2023 20:08:24 +0330 Subject: [PATCH 192/775] Fix comments --- render/march3.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/render/march3.go b/render/march3.go index 1f38eb307..b1b4e678d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -361,18 +361,19 @@ var mcEdgeTable = [256]int{ var mcTriangleTable = [256][]int{ // Case 0 {}, - // Case 2 + // Case 1 {0, 8, 3}, - // Case 3 + // Case 2 {0, 1, 9}, - // Case 4 + // Case 3 {1, 8, 3, 9, 8, 1}, - // Case 5 + // Case 4 {1, 2, 10}, - // Case 6 + // Case 5 {0, 8, 3, 1, 2, 10}, - // Case 7 + // Case 6 {9, 2, 10, 0, 2, 9}, + // Case 7 {2, 8, 3, 2, 10, 8, 10, 9, 8}, {3, 11, 2}, {0, 11, 2, 8, 11, 0}, From 2311674ce7381c19983d09e60fe9a3be2e28e3df Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 09:39:23 +0330 Subject: [PATCH 193/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b1b4e678d..9537fff76 100644 --- a/render/march3.go +++ b/render/march3.go @@ -375,6 +375,7 @@ var mcTriangleTable = [256][]int{ {9, 2, 10, 0, 2, 9}, // Case 7 {2, 8, 3, 2, 10, 8, 10, 9, 8}, + // Case 8 {3, 11, 2}, {0, 11, 2, 8, 11, 0}, {1, 9, 0, 2, 3, 11}, From fec8d14d15c314b95bfa8abcc6f88e8119e20aac Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 11:20:05 +0330 Subject: [PATCH 194/775] Comment: binary case numbers --- render/march3.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/render/march3.go b/render/march3.go index 9537fff76..24b888519 100644 --- a/render/march3.go +++ b/render/march3.go @@ -359,23 +359,23 @@ var mcEdgeTable = [256]int{ // specify the edges used to create the triangle(s) var mcTriangleTable = [256][]int{ - // Case 0 + // 0b00000000 Case 0 {}, - // Case 1 + // 0b00000001 Case 1 {0, 8, 3}, - // Case 2 + // 0b00000010 Case 2 {0, 1, 9}, - // Case 3 + // 0b00000011 Case 3 {1, 8, 3, 9, 8, 1}, - // Case 4 + // 0b00000100 Case 4 {1, 2, 10}, - // Case 5 + // 0b00000101 Case 5 {0, 8, 3, 1, 2, 10}, - // Case 6 + // 0b00000110 Case 6 {9, 2, 10, 0, 2, 9}, - // Case 7 + // 0b00000111 Case 7 {2, 8, 3, 2, 10, 8, 10, 9, 8}, - // Case 8 + // 0b00001000 Case 8 {3, 11, 2}, {0, 11, 2, 8, 11, 0}, {1, 9, 0, 2, 3, 11}, From b8747fdd5631e8438235534146f11571ffc9bcff Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 11:22:44 +0330 Subject: [PATCH 195/775] Comment --- render/march3.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/render/march3.go b/render/march3.go index 24b888519..b3da77362 100644 --- a/render/march3.go +++ b/render/march3.go @@ -359,23 +359,23 @@ var mcEdgeTable = [256]int{ // specify the edges used to create the triangle(s) var mcTriangleTable = [256][]int{ - // 0b00000000 Case 0 + // 0b00000000 case 0 {}, - // 0b00000001 Case 1 + // 0b00000001 case 1 {0, 8, 3}, - // 0b00000010 Case 2 + // 0b00000010 case 2 {0, 1, 9}, - // 0b00000011 Case 3 + // 0b00000011 case 3 {1, 8, 3, 9, 8, 1}, - // 0b00000100 Case 4 + // 0b00000100 case 4 {1, 2, 10}, - // 0b00000101 Case 5 + // 0b00000101 case 5 {0, 8, 3, 1, 2, 10}, - // 0b00000110 Case 6 + // 0b00000110 case 6 {9, 2, 10, 0, 2, 9}, - // 0b00000111 Case 7 + // 0b00000111 case 7 {2, 8, 3, 2, 10, 8, 10, 9, 8}, - // 0b00001000 Case 8 + // 0b00001000 case 8 {3, 11, 2}, {0, 11, 2, 8, 11, 0}, {1, 9, 0, 2, 3, 11}, From fca05f1dcd4cda87bfb9f2100d958e9da7a18afe Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 11:24:04 +0330 Subject: [PATCH 196/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b3da77362..a0e8e5b72 100644 --- a/render/march3.go +++ b/render/march3.go @@ -377,6 +377,7 @@ var mcTriangleTable = [256][]int{ {2, 8, 3, 2, 10, 8, 10, 9, 8}, // 0b00001000 case 8 {3, 11, 2}, + // 0b00001001 case 9 {0, 11, 2, 8, 11, 0}, {1, 9, 0, 2, 3, 11}, {1, 11, 2, 1, 9, 11, 9, 8, 11}, From b80891b56ef6518034c7e09521555d5ee9020ec8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 12:39:11 +0330 Subject: [PATCH 197/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a0e8e5b72..b985f6b00 100644 --- a/render/march3.go +++ b/render/march3.go @@ -379,6 +379,7 @@ var mcTriangleTable = [256][]int{ {3, 11, 2}, // 0b00001001 case 9 {0, 11, 2, 8, 11, 0}, + // 0b00001010 case 10 {1, 9, 0, 2, 3, 11}, {1, 11, 2, 1, 9, 11, 9, 8, 11}, {3, 10, 1, 11, 10, 3}, From d0dd16a5af6302f73834ad6fd07022f03aa06ae5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 12:47:38 +0330 Subject: [PATCH 198/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b985f6b00..134f44f52 100644 --- a/render/march3.go +++ b/render/march3.go @@ -381,6 +381,7 @@ var mcTriangleTable = [256][]int{ {0, 11, 2, 8, 11, 0}, // 0b00001010 case 10 {1, 9, 0, 2, 3, 11}, + // 0b00001011 case 11 {1, 11, 2, 1, 9, 11, 9, 8, 11}, {3, 10, 1, 11, 10, 3}, {0, 10, 1, 0, 8, 10, 8, 11, 10}, From 33826b644618a010299f37ea932543680e9d1c71 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 12:59:27 +0330 Subject: [PATCH 199/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 134f44f52..12765ca37 100644 --- a/render/march3.go +++ b/render/march3.go @@ -383,6 +383,7 @@ var mcTriangleTable = [256][]int{ {1, 9, 0, 2, 3, 11}, // 0b00001011 case 11 {1, 11, 2, 1, 9, 11, 9, 8, 11}, + // 0b00001100 case 12 {3, 10, 1, 11, 10, 3}, {0, 10, 1, 0, 8, 10, 8, 11, 10}, {3, 9, 0, 3, 11, 9, 11, 10, 9}, From f8a23c32440ee2de88e78d3f68bbbe06b7fdeb30 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 14:37:08 +0330 Subject: [PATCH 200/775] Comment --- render/march3.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/render/march3.go b/render/march3.go index 12765ca37..30bca1452 100644 --- a/render/march3.go +++ b/render/march3.go @@ -385,7 +385,9 @@ var mcTriangleTable = [256][]int{ {1, 11, 2, 1, 9, 11, 9, 8, 11}, // 0b00001100 case 12 {3, 10, 1, 11, 10, 3}, + // 0b00001101 case 13 {0, 10, 1, 0, 8, 10, 8, 11, 10}, + // 0b00001110 case 14 {3, 9, 0, 3, 11, 9, 11, 10, 9}, {9, 8, 10, 10, 8, 11}, {4, 7, 8}, From b9b1be7c852893bb7784b0f02a05690c59f2f200 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 15:26:12 +0330 Subject: [PATCH 201/775] Comment --- render/march3.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/render/march3.go b/render/march3.go index 30bca1452..7ffbb9bd9 100644 --- a/render/march3.go +++ b/render/march3.go @@ -389,8 +389,11 @@ var mcTriangleTable = [256][]int{ {0, 10, 1, 0, 8, 10, 8, 11, 10}, // 0b00001110 case 14 {3, 9, 0, 3, 11, 9, 11, 10, 9}, + // 0b00001111 case 15 {9, 8, 10, 10, 8, 11}, + // 0b00010000 case 16 {4, 7, 8}, + // 0b00010001 case 17 {4, 3, 0, 7, 3, 4}, {0, 1, 9, 8, 4, 7}, {4, 1, 9, 4, 7, 1, 7, 3, 1}, From 72c31351c9cc1af5c7b8643c5d45803fdc9ffa41 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 15:36:06 +0330 Subject: [PATCH 202/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7ffbb9bd9..fdeb4c66d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -395,6 +395,7 @@ var mcTriangleTable = [256][]int{ {4, 7, 8}, // 0b00010001 case 17 {4, 3, 0, 7, 3, 4}, + // 0b00010010 case 18 {0, 1, 9, 8, 4, 7}, {4, 1, 9, 4, 7, 1, 7, 3, 1}, {1, 2, 10, 8, 4, 7}, From fbd0ca0f17fb97c3776d4d90051da6578b6188aa Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 15:49:57 +0330 Subject: [PATCH 203/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fdeb4c66d..d3d5763d7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -397,6 +397,7 @@ var mcTriangleTable = [256][]int{ {4, 3, 0, 7, 3, 4}, // 0b00010010 case 18 {0, 1, 9, 8, 4, 7}, + // 0b00010011 case 19 {4, 1, 9, 4, 7, 1, 7, 3, 1}, {1, 2, 10, 8, 4, 7}, {3, 4, 7, 3, 0, 4, 1, 2, 10}, From 75a2c397b64f4e4ff861a7d201d2f99e106d9ad4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 16:07:13 +0330 Subject: [PATCH 204/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d3d5763d7..8276aa484 100644 --- a/render/march3.go +++ b/render/march3.go @@ -399,6 +399,7 @@ var mcTriangleTable = [256][]int{ {0, 1, 9, 8, 4, 7}, // 0b00010011 case 19 {4, 1, 9, 4, 7, 1, 7, 3, 1}, + // 0b00010100 case 20 {1, 2, 10, 8, 4, 7}, {3, 4, 7, 3, 0, 4, 1, 2, 10}, {9, 2, 10, 9, 0, 2, 8, 4, 7}, From fcb703335234e4ce1afa6adc4a0ff8fe96dd76d6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 16:17:52 +0330 Subject: [PATCH 205/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8276aa484..36a4c526a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -401,6 +401,7 @@ var mcTriangleTable = [256][]int{ {4, 1, 9, 4, 7, 1, 7, 3, 1}, // 0b00010100 case 20 {1, 2, 10, 8, 4, 7}, + // 0b00010101 case 21 {3, 4, 7, 3, 0, 4, 1, 2, 10}, {9, 2, 10, 9, 0, 2, 8, 4, 7}, {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4}, From 066673c676b60be68f47cc915034fab59239b248 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 16:31:20 +0330 Subject: [PATCH 206/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 36a4c526a..2595ae483 100644 --- a/render/march3.go +++ b/render/march3.go @@ -403,6 +403,7 @@ var mcTriangleTable = [256][]int{ {1, 2, 10, 8, 4, 7}, // 0b00010101 case 21 {3, 4, 7, 3, 0, 4, 1, 2, 10}, + // 0b00010110 case 22 {9, 2, 10, 9, 0, 2, 8, 4, 7}, {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4}, {8, 4, 7, 3, 11, 2}, From fec55667a6dd0dfcbb00565c0b07d5fc734f522d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 16:39:38 +0330 Subject: [PATCH 207/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 2595ae483..5876f9972 100644 --- a/render/march3.go +++ b/render/march3.go @@ -405,6 +405,7 @@ var mcTriangleTable = [256][]int{ {3, 4, 7, 3, 0, 4, 1, 2, 10}, // 0b00010110 case 22 {9, 2, 10, 9, 0, 2, 8, 4, 7}, + // 0b00010111 case 23 {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4}, {8, 4, 7, 3, 11, 2}, {11, 4, 7, 11, 2, 4, 2, 0, 4}, From 19131ec7cfca227a57b2758c017d8655e09a694f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 16:56:48 +0330 Subject: [PATCH 208/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 5876f9972..6dfe7f658 100644 --- a/render/march3.go +++ b/render/march3.go @@ -407,6 +407,7 @@ var mcTriangleTable = [256][]int{ {9, 2, 10, 9, 0, 2, 8, 4, 7}, // 0b00010111 case 23 {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4}, + // 0b00011000 case 24 {8, 4, 7, 3, 11, 2}, {11, 4, 7, 11, 2, 4, 2, 0, 4}, {9, 0, 1, 8, 4, 7, 2, 3, 11}, From 3457e99d42ddde68e09b88f439a0d6e9a7c7a198 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 17:04:30 +0330 Subject: [PATCH 209/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 6dfe7f658..40fd2849a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -409,6 +409,7 @@ var mcTriangleTable = [256][]int{ {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4}, // 0b00011000 case 24 {8, 4, 7, 3, 11, 2}, + // 0b00011001 case 25 {11, 4, 7, 11, 2, 4, 2, 0, 4}, {9, 0, 1, 8, 4, 7, 2, 3, 11}, {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1}, From 3010e6b936b0b50b4bbc93e3350ce83856cfdb4e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 17:44:03 +0330 Subject: [PATCH 210/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 40fd2849a..5562a3ec0 100644 --- a/render/march3.go +++ b/render/march3.go @@ -411,6 +411,7 @@ var mcTriangleTable = [256][]int{ {8, 4, 7, 3, 11, 2}, // 0b00011001 case 25 {11, 4, 7, 11, 2, 4, 2, 0, 4}, + // 0b00011010 case 26 {9, 0, 1, 8, 4, 7, 2, 3, 11}, {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1}, {3, 10, 1, 3, 11, 10, 7, 8, 4}, From b1da56aa91cbb333ffaaa8b734a3eefb5aae54af Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 17:51:05 +0330 Subject: [PATCH 211/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 5562a3ec0..2745929c8 100644 --- a/render/march3.go +++ b/render/march3.go @@ -413,6 +413,7 @@ var mcTriangleTable = [256][]int{ {11, 4, 7, 11, 2, 4, 2, 0, 4}, // 0b00011010 case 26 {9, 0, 1, 8, 4, 7, 2, 3, 11}, + // 0b00011011 case 27 {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1}, {3, 10, 1, 3, 11, 10, 7, 8, 4}, {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4}, From f2cac3e46dc2053fc65ede81505107841905f1b5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 18:31:31 +0330 Subject: [PATCH 212/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 2745929c8..be2c6e93a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -415,6 +415,7 @@ var mcTriangleTable = [256][]int{ {9, 0, 1, 8, 4, 7, 2, 3, 11}, // 0b00011011 case 27 {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1}, + // 0b00011100 case 28 {3, 10, 1, 3, 11, 10, 7, 8, 4}, {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4}, {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3}, From 0b3c459055eb88f54bdb1e4fa57aeb92c15a0b4b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 18:41:24 +0330 Subject: [PATCH 213/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index be2c6e93a..ed5299215 100644 --- a/render/march3.go +++ b/render/march3.go @@ -417,6 +417,7 @@ var mcTriangleTable = [256][]int{ {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1}, // 0b00011100 case 28 {3, 10, 1, 3, 11, 10, 7, 8, 4}, + // 0b00011101 case 29 {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4}, {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3}, {4, 7, 11, 4, 11, 9, 9, 11, 10}, From 76e2ae916ee254df46963bbf9838cbc270835aaa Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 19:01:49 +0330 Subject: [PATCH 214/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ed5299215..d9f9df69e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -419,6 +419,7 @@ var mcTriangleTable = [256][]int{ {3, 10, 1, 3, 11, 10, 7, 8, 4}, // 0b00011101 case 29 {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4}, + // 0b00011110 case 30 {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3}, {4, 7, 11, 4, 11, 9, 9, 11, 10}, {9, 5, 4}, From 15b894bfb0d3d7d7739b8f52a30ad4815af0a681 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 21:24:27 +0330 Subject: [PATCH 215/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d9f9df69e..8121e88c5 100644 --- a/render/march3.go +++ b/render/march3.go @@ -421,6 +421,7 @@ var mcTriangleTable = [256][]int{ {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4}, // 0b00011110 case 30 {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3}, + // 0b00011111 case 31 {4, 7, 11, 4, 11, 9, 9, 11, 10}, {9, 5, 4}, {9, 5, 4, 0, 8, 3}, From ef5529153ac99c064ee8c53bd1eba3387c7b08ff Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 21:35:23 +0330 Subject: [PATCH 216/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8121e88c5..f77bec332 100644 --- a/render/march3.go +++ b/render/march3.go @@ -423,6 +423,7 @@ var mcTriangleTable = [256][]int{ {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3}, // 0b00011111 case 31 {4, 7, 11, 4, 11, 9, 9, 11, 10}, + // 0b00100000 case 32 {9, 5, 4}, {9, 5, 4, 0, 8, 3}, {0, 5, 4, 1, 5, 0}, From ff79ad5ef6cb020690b9892647d46bd4120b8764 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 21:43:32 +0330 Subject: [PATCH 217/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index f77bec332..2a7b5fb84 100644 --- a/render/march3.go +++ b/render/march3.go @@ -425,6 +425,7 @@ var mcTriangleTable = [256][]int{ {4, 7, 11, 4, 11, 9, 9, 11, 10}, // 0b00100000 case 32 {9, 5, 4}, + // 0b00100001 case 33 {9, 5, 4, 0, 8, 3}, {0, 5, 4, 1, 5, 0}, {8, 5, 4, 8, 3, 5, 3, 1, 5}, From b8ec56ac88e2b11e5b1f24326a714c2346d44bbc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 21:52:43 +0330 Subject: [PATCH 218/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 2a7b5fb84..05f58a4ca 100644 --- a/render/march3.go +++ b/render/march3.go @@ -427,6 +427,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 4}, // 0b00100001 case 33 {9, 5, 4, 0, 8, 3}, + // 0b00100010 case 34 {0, 5, 4, 1, 5, 0}, {8, 5, 4, 8, 3, 5, 3, 1, 5}, {1, 2, 10, 9, 5, 4}, From eb8a98b3a5eff29beee36fb4c30402a0ac24a33d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 16 May 2023 22:01:09 +0330 Subject: [PATCH 219/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 05f58a4ca..0dfe9955c 100644 --- a/render/march3.go +++ b/render/march3.go @@ -429,6 +429,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 4, 0, 8, 3}, // 0b00100010 case 34 {0, 5, 4, 1, 5, 0}, + // 0b00100011 case 35 {8, 5, 4, 8, 3, 5, 3, 1, 5}, {1, 2, 10, 9, 5, 4}, {3, 0, 8, 1, 2, 10, 4, 9, 5}, From eda592d3b639ae33d1fce5cc6abe32bba46fba5f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 07:46:29 +0330 Subject: [PATCH 220/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 0dfe9955c..1e08177b8 100644 --- a/render/march3.go +++ b/render/march3.go @@ -431,6 +431,7 @@ var mcTriangleTable = [256][]int{ {0, 5, 4, 1, 5, 0}, // 0b00100011 case 35 {8, 5, 4, 8, 3, 5, 3, 1, 5}, + // 0b00100100 case 36 {1, 2, 10, 9, 5, 4}, {3, 0, 8, 1, 2, 10, 4, 9, 5}, {5, 2, 10, 5, 4, 2, 4, 0, 2}, From d9c74a04d0c3d991379c0161c7ac6f4ad9d9a8bd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 07:53:47 +0330 Subject: [PATCH 221/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 1e08177b8..7827f0ca3 100644 --- a/render/march3.go +++ b/render/march3.go @@ -433,6 +433,7 @@ var mcTriangleTable = [256][]int{ {8, 5, 4, 8, 3, 5, 3, 1, 5}, // 0b00100100 case 36 {1, 2, 10, 9, 5, 4}, + // 0b00100101 case 37 {3, 0, 8, 1, 2, 10, 4, 9, 5}, {5, 2, 10, 5, 4, 2, 4, 0, 2}, {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8}, From a542a263ee8bbdd0a04aa2762c7ddbadad1007e2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 08:00:21 +0330 Subject: [PATCH 222/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7827f0ca3..75120443a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -435,6 +435,7 @@ var mcTriangleTable = [256][]int{ {1, 2, 10, 9, 5, 4}, // 0b00100101 case 37 {3, 0, 8, 1, 2, 10, 4, 9, 5}, + // 0b00100110 case 38 {5, 2, 10, 5, 4, 2, 4, 0, 2}, {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8}, {9, 5, 4, 2, 3, 11}, From 1e37e2c4b544d9614366de804f2023bb7c1201a5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 11:32:04 +0330 Subject: [PATCH 223/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 75120443a..b67a8d451 100644 --- a/render/march3.go +++ b/render/march3.go @@ -437,6 +437,7 @@ var mcTriangleTable = [256][]int{ {3, 0, 8, 1, 2, 10, 4, 9, 5}, // 0b00100110 case 38 {5, 2, 10, 5, 4, 2, 4, 0, 2}, + // 0b00100111 case 39 {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8}, {9, 5, 4, 2, 3, 11}, {0, 11, 2, 0, 8, 11, 4, 9, 5}, From e569cd14539b6874aa00b650b904c6c5c9a7b354 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 11:55:32 +0330 Subject: [PATCH 224/775] Case 40 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b67a8d451..d0f4383ae 100644 --- a/render/march3.go +++ b/render/march3.go @@ -439,6 +439,7 @@ var mcTriangleTable = [256][]int{ {5, 2, 10, 5, 4, 2, 4, 0, 2}, // 0b00100111 case 39 {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8}, + // 0b00101000 case 40 {9, 5, 4, 2, 3, 11}, {0, 11, 2, 0, 8, 11, 4, 9, 5}, {0, 5, 4, 0, 1, 5, 2, 3, 11}, From e761053e2e1f2224fa487666dcef8680ff64fa6a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 12:07:48 +0330 Subject: [PATCH 225/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d0f4383ae..9457fd62c 100644 --- a/render/march3.go +++ b/render/march3.go @@ -441,6 +441,7 @@ var mcTriangleTable = [256][]int{ {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8}, // 0b00101000 case 40 {9, 5, 4, 2, 3, 11}, + // 0b00101001 case 41 {0, 11, 2, 0, 8, 11, 4, 9, 5}, {0, 5, 4, 0, 1, 5, 2, 3, 11}, {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5}, From a90a6ce6fb01f0ac00dd25cd56e37cfc0def4e1a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 12:20:19 +0330 Subject: [PATCH 226/775] Case 42 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9457fd62c..7113efb08 100644 --- a/render/march3.go +++ b/render/march3.go @@ -443,6 +443,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 4, 2, 3, 11}, // 0b00101001 case 41 {0, 11, 2, 0, 8, 11, 4, 9, 5}, + // 0b00101010 case 42 {0, 5, 4, 0, 1, 5, 2, 3, 11}, {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5}, {10, 3, 11, 10, 1, 3, 9, 5, 4}, From afaf34e17d1e241181ec3b296fa7ae85edef12bc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 12:27:11 +0330 Subject: [PATCH 227/775] Case 43 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7113efb08..fbce52325 100644 --- a/render/march3.go +++ b/render/march3.go @@ -445,6 +445,7 @@ var mcTriangleTable = [256][]int{ {0, 11, 2, 0, 8, 11, 4, 9, 5}, // 0b00101010 case 42 {0, 5, 4, 0, 1, 5, 2, 3, 11}, + // 0b00101011 case 43 {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5}, {10, 3, 11, 10, 1, 3, 9, 5, 4}, {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10}, From 954a4d55b6a92b4d688937a527fb30a102715a35 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 12:38:34 +0330 Subject: [PATCH 228/775] Case 44 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fbce52325..b9bd47b30 100644 --- a/render/march3.go +++ b/render/march3.go @@ -447,6 +447,7 @@ var mcTriangleTable = [256][]int{ {0, 5, 4, 0, 1, 5, 2, 3, 11}, // 0b00101011 case 43 {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5}, + // 0b00101100 case 44 {10, 3, 11, 10, 1, 3, 9, 5, 4}, {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10}, {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3}, From 12134f99adf1fa3d36809a0e1236d25b54b0cc82 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 12:45:18 +0330 Subject: [PATCH 229/775] Case 45 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b9bd47b30..4f832552d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -449,6 +449,7 @@ var mcTriangleTable = [256][]int{ {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5}, // 0b00101100 case 44 {10, 3, 11, 10, 1, 3, 9, 5, 4}, + // 0b00101101 case 45 {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10}, {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3}, {5, 4, 8, 5, 8, 10, 10, 8, 11}, From 0470a29281a37770ef73d059d551273e0b60f825 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 12:55:59 +0330 Subject: [PATCH 230/775] Case 46 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 4f832552d..cdcd721e4 100644 --- a/render/march3.go +++ b/render/march3.go @@ -451,6 +451,7 @@ var mcTriangleTable = [256][]int{ {10, 3, 11, 10, 1, 3, 9, 5, 4}, // 0b00101101 case 45 {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10}, + // 0b00101110 case 46 {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3}, {5, 4, 8, 5, 8, 10, 10, 8, 11}, {9, 7, 8, 5, 7, 9}, From 62edbb82ad55f41e84c70f9ead8b41e444905898 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 13:15:21 +0330 Subject: [PATCH 231/775] Case 47 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index cdcd721e4..8a68d9995 100644 --- a/render/march3.go +++ b/render/march3.go @@ -453,6 +453,7 @@ var mcTriangleTable = [256][]int{ {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10}, // 0b00101110 case 46 {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3}, + // 0b00101111 case 47 {5, 4, 8, 5, 8, 10, 10, 8, 11}, {9, 7, 8, 5, 7, 9}, {9, 3, 0, 9, 5, 3, 5, 7, 3}, From 90541791b64f04c890dfded889ddb65df6440d1d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 13:33:17 +0330 Subject: [PATCH 232/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8a68d9995..ddb010842 100644 --- a/render/march3.go +++ b/render/march3.go @@ -455,6 +455,7 @@ var mcTriangleTable = [256][]int{ {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3}, // 0b00101111 case 47 {5, 4, 8, 5, 8, 10, 10, 8, 11}, + // 0b00110000 case 48 {9, 7, 8, 5, 7, 9}, {9, 3, 0, 9, 5, 3, 5, 7, 3}, {0, 7, 8, 0, 1, 7, 1, 5, 7}, From 52053dc9e043fdea1b0ebf3ed733b54220d007ee Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 13:42:16 +0330 Subject: [PATCH 233/775] Case 49 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ddb010842..20cf3ee27 100644 --- a/render/march3.go +++ b/render/march3.go @@ -457,6 +457,7 @@ var mcTriangleTable = [256][]int{ {5, 4, 8, 5, 8, 10, 10, 8, 11}, // 0b00110000 case 48 {9, 7, 8, 5, 7, 9}, + // 0b00110001 case 49 {9, 3, 0, 9, 5, 3, 5, 7, 3}, {0, 7, 8, 0, 1, 7, 1, 5, 7}, {1, 5, 3, 3, 5, 7}, From 98613d1745206a6b1f150e31069475b39c7f2be4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 13:54:20 +0330 Subject: [PATCH 234/775] Case 50 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 20cf3ee27..ea3f0907b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -459,6 +459,7 @@ var mcTriangleTable = [256][]int{ {9, 7, 8, 5, 7, 9}, // 0b00110001 case 49 {9, 3, 0, 9, 5, 3, 5, 7, 3}, + // 0b00110010 case 50 {0, 7, 8, 0, 1, 7, 1, 5, 7}, {1, 5, 3, 3, 5, 7}, {9, 7, 8, 9, 5, 7, 10, 1, 2}, From c373f028e2ae321cd3f9e8485ffdebe6aae6c230 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 14:03:50 +0330 Subject: [PATCH 235/775] Case 51 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ea3f0907b..53b88a790 100644 --- a/render/march3.go +++ b/render/march3.go @@ -461,6 +461,7 @@ var mcTriangleTable = [256][]int{ {9, 3, 0, 9, 5, 3, 5, 7, 3}, // 0b00110010 case 50 {0, 7, 8, 0, 1, 7, 1, 5, 7}, + // 0b00110011 case 51 {1, 5, 3, 3, 5, 7}, {9, 7, 8, 9, 5, 7, 10, 1, 2}, {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3}, From 949784a4dd648391e1e9757d6fc91ef5607986ca Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 14:17:23 +0330 Subject: [PATCH 236/775] Case 52 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 53b88a790..a55477b8b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -463,6 +463,7 @@ var mcTriangleTable = [256][]int{ {0, 7, 8, 0, 1, 7, 1, 5, 7}, // 0b00110011 case 51 {1, 5, 3, 3, 5, 7}, + // 0b00110100 case 52 {9, 7, 8, 9, 5, 7, 10, 1, 2}, {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3}, {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2}, From d175a082eb86713d59282fb89849d523dac33eb8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 14:28:20 +0330 Subject: [PATCH 237/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a55477b8b..3888bdb30 100644 --- a/render/march3.go +++ b/render/march3.go @@ -465,6 +465,7 @@ var mcTriangleTable = [256][]int{ {1, 5, 3, 3, 5, 7}, // 0b00110100 case 52 {9, 7, 8, 9, 5, 7, 10, 1, 2}, + // 0b00110101 case 53 {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3}, {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2}, {2, 10, 5, 2, 5, 3, 3, 5, 7}, From fb225412a1ffa6f4e6f4d44155e02515ef9abae1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 16:15:20 +0330 Subject: [PATCH 238/775] Comment --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 3888bdb30..aaead5aac 100644 --- a/render/march3.go +++ b/render/march3.go @@ -467,6 +467,7 @@ var mcTriangleTable = [256][]int{ {9, 7, 8, 9, 5, 7, 10, 1, 2}, // 0b00110101 case 53 {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3}, + // 0b00110110 case 54 {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2}, {2, 10, 5, 2, 5, 3, 3, 5, 7}, {7, 9, 5, 7, 8, 9, 3, 11, 2}, From 6c2a5db696c31985a7be9665296f9faf56d57a72 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 16:28:31 +0330 Subject: [PATCH 239/775] Case 55 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index aaead5aac..9ec6b0501 100644 --- a/render/march3.go +++ b/render/march3.go @@ -469,6 +469,7 @@ var mcTriangleTable = [256][]int{ {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3}, // 0b00110110 case 54 {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2}, + // 0b00110111 case 55 {2, 10, 5, 2, 5, 3, 3, 5, 7}, {7, 9, 5, 7, 8, 9, 3, 11, 2}, {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11}, From b2b96bd4bcf301aedafd173a48f58131d9338392 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 16:38:59 +0330 Subject: [PATCH 240/775] Case 56 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9ec6b0501..8554e6392 100644 --- a/render/march3.go +++ b/render/march3.go @@ -471,6 +471,7 @@ var mcTriangleTable = [256][]int{ {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2}, // 0b00110111 case 55 {2, 10, 5, 2, 5, 3, 3, 5, 7}, + // 0b00111000 case 56 {7, 9, 5, 7, 8, 9, 3, 11, 2}, {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11}, {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7}, From 214fff7ea8cce4b1e82fab21eec3273a585ba2bb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 16:46:15 +0330 Subject: [PATCH 241/775] Case 57 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8554e6392..717a23b27 100644 --- a/render/march3.go +++ b/render/march3.go @@ -473,6 +473,7 @@ var mcTriangleTable = [256][]int{ {2, 10, 5, 2, 5, 3, 3, 5, 7}, // 0b00111000 case 56 {7, 9, 5, 7, 8, 9, 3, 11, 2}, + // 0b00111001 case 57 {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11}, {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7}, {11, 2, 1, 11, 1, 7, 7, 1, 5}, From 045b7524c44312c4653fd747fe48bd53936af5eb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 16:59:43 +0330 Subject: [PATCH 242/775] Case 58 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 717a23b27..34eeb3acd 100644 --- a/render/march3.go +++ b/render/march3.go @@ -475,6 +475,7 @@ var mcTriangleTable = [256][]int{ {7, 9, 5, 7, 8, 9, 3, 11, 2}, // 0b00111001 case 57 {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11}, + // 0b00111010 case 58 {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7}, {11, 2, 1, 11, 1, 7, 7, 1, 5}, {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11}, From 2d37e0bf8a7ed0e0e22015364451b91d3c87daea Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 17:10:41 +0330 Subject: [PATCH 243/775] Case 59 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 34eeb3acd..a1989399e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -477,6 +477,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11}, // 0b00111010 case 58 {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7}, + // 0b00111011 case 59 {11, 2, 1, 11, 1, 7, 7, 1, 5}, {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11}, {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0}, From d4422db8cef712cdec25c9fb1a63bbdc73918a1e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 17:23:17 +0330 Subject: [PATCH 244/775] Case 60 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a1989399e..89b4fd159 100644 --- a/render/march3.go +++ b/render/march3.go @@ -479,6 +479,7 @@ var mcTriangleTable = [256][]int{ {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7}, // 0b00111011 case 59 {11, 2, 1, 11, 1, 7, 7, 1, 5}, + // 0b00111100 case 60 {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11}, {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0}, {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0}, From 17ca57b79feceadb75f73f0d3dc0403cbc69a862 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 17:34:00 +0330 Subject: [PATCH 245/775] Case 61 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 89b4fd159..9600060e6 100644 --- a/render/march3.go +++ b/render/march3.go @@ -481,6 +481,7 @@ var mcTriangleTable = [256][]int{ {11, 2, 1, 11, 1, 7, 7, 1, 5}, // 0b00111100 case 60 {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11}, + // 0b00111101 case 61 {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0}, {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0}, {11, 10, 5, 7, 11, 5}, From c6cb69c3c527f9f1834698cab707ef49f7fc87fe Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 17:49:52 +0330 Subject: [PATCH 246/775] Case 62 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9600060e6..283c0dcf1 100644 --- a/render/march3.go +++ b/render/march3.go @@ -483,6 +483,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11}, // 0b00111101 case 61 {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0}, + // 0b00111110 case 62 {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0}, {11, 10, 5, 7, 11, 5}, {10, 6, 5}, From 9f92823536c27ed022a3409b904f3c4e86b35f20 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 18:01:35 +0330 Subject: [PATCH 247/775] Case 63 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 283c0dcf1..3efb351a7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -485,6 +485,7 @@ var mcTriangleTable = [256][]int{ {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0}, // 0b00111110 case 62 {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0}, + // 0b00111111 case 63 {11, 10, 5, 7, 11, 5}, {10, 6, 5}, {0, 8, 3, 5, 10, 6}, From 4e6d2a6888b52a74df5a1abd467df915df166f3e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 18:13:20 +0330 Subject: [PATCH 248/775] Case 64 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 3efb351a7..51b4f66a7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -487,6 +487,7 @@ var mcTriangleTable = [256][]int{ {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0}, // 0b00111111 case 63 {11, 10, 5, 7, 11, 5}, + // 0b01000000 case 64 {10, 6, 5}, {0, 8, 3, 5, 10, 6}, {9, 0, 1, 5, 10, 6}, From 3882690b3e3d4e4272d9feae9194cd3684f4de28 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 18:20:21 +0330 Subject: [PATCH 249/775] Case 65 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 51b4f66a7..2ada24781 100644 --- a/render/march3.go +++ b/render/march3.go @@ -489,6 +489,7 @@ var mcTriangleTable = [256][]int{ {11, 10, 5, 7, 11, 5}, // 0b01000000 case 64 {10, 6, 5}, + // 0b01000001 case 65 {0, 8, 3, 5, 10, 6}, {9, 0, 1, 5, 10, 6}, {1, 8, 3, 1, 9, 8, 5, 10, 6}, From be1dc5b72c1c84552c88c56774b7adb2c5ebb923 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 18:26:07 +0330 Subject: [PATCH 250/775] Case 66 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 2ada24781..905afa9e9 100644 --- a/render/march3.go +++ b/render/march3.go @@ -491,6 +491,7 @@ var mcTriangleTable = [256][]int{ {10, 6, 5}, // 0b01000001 case 65 {0, 8, 3, 5, 10, 6}, + // 0b01000010 case 66 {9, 0, 1, 5, 10, 6}, {1, 8, 3, 1, 9, 8, 5, 10, 6}, {1, 6, 5, 2, 6, 1}, From ed583fb655ebb3cd8f4a9b41f3b8a9a539301fc8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 18:30:55 +0330 Subject: [PATCH 251/775] Case 67 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 905afa9e9..537dddc3b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -493,6 +493,7 @@ var mcTriangleTable = [256][]int{ {0, 8, 3, 5, 10, 6}, // 0b01000010 case 66 {9, 0, 1, 5, 10, 6}, + // 0b01000011 case 67 {1, 8, 3, 1, 9, 8, 5, 10, 6}, {1, 6, 5, 2, 6, 1}, {1, 6, 5, 1, 2, 6, 3, 0, 8}, From ba98dc72884a5f8765a2a5b9ea8ff0f8a1787d33 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 17 May 2023 18:38:41 +0330 Subject: [PATCH 252/775] Case 68 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 537dddc3b..b44375f67 100644 --- a/render/march3.go +++ b/render/march3.go @@ -495,6 +495,7 @@ var mcTriangleTable = [256][]int{ {9, 0, 1, 5, 10, 6}, // 0b01000011 case 67 {1, 8, 3, 1, 9, 8, 5, 10, 6}, + // 0b01000100 case 68 {1, 6, 5, 2, 6, 1}, {1, 6, 5, 1, 2, 6, 3, 0, 8}, {9, 6, 5, 9, 0, 6, 0, 2, 6}, From f94eb25d81e764c3ec96f89c01c10e714829b5b7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 08:56:07 +0330 Subject: [PATCH 253/775] Case 69 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b44375f67..1af1e6b83 100644 --- a/render/march3.go +++ b/render/march3.go @@ -497,6 +497,7 @@ var mcTriangleTable = [256][]int{ {1, 8, 3, 1, 9, 8, 5, 10, 6}, // 0b01000100 case 68 {1, 6, 5, 2, 6, 1}, + // 0b01000101 case 69 {1, 6, 5, 1, 2, 6, 3, 0, 8}, {9, 6, 5, 9, 0, 6, 0, 2, 6}, {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8}, From 54fcee6a157874152b9c32f884d11d8ff9e970b8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 09:03:36 +0330 Subject: [PATCH 254/775] Case 70 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 1af1e6b83..a6ba96587 100644 --- a/render/march3.go +++ b/render/march3.go @@ -499,6 +499,7 @@ var mcTriangleTable = [256][]int{ {1, 6, 5, 2, 6, 1}, // 0b01000101 case 69 {1, 6, 5, 1, 2, 6, 3, 0, 8}, + // 0b01000110 case 70 {9, 6, 5, 9, 0, 6, 0, 2, 6}, {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8}, {2, 3, 11, 10, 6, 5}, From 76962c1b87f6135940ccb92a7dace75ab898332a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 09:14:18 +0330 Subject: [PATCH 255/775] Case 71 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a6ba96587..1d1d85142 100644 --- a/render/march3.go +++ b/render/march3.go @@ -501,6 +501,7 @@ var mcTriangleTable = [256][]int{ {1, 6, 5, 1, 2, 6, 3, 0, 8}, // 0b01000110 case 70 {9, 6, 5, 9, 0, 6, 0, 2, 6}, + // 0b01000111 case 71 {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8}, {2, 3, 11, 10, 6, 5}, {11, 0, 8, 11, 2, 0, 10, 6, 5}, From aadfcc31273e383753cccdd4e88cd66e91d2c18f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 09:27:21 +0330 Subject: [PATCH 256/775] Case 72 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 1d1d85142..b6f94f350 100644 --- a/render/march3.go +++ b/render/march3.go @@ -503,6 +503,7 @@ var mcTriangleTable = [256][]int{ {9, 6, 5, 9, 0, 6, 0, 2, 6}, // 0b01000111 case 71 {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8}, + // 0b01001000 case 72 {2, 3, 11, 10, 6, 5}, {11, 0, 8, 11, 2, 0, 10, 6, 5}, {0, 1, 9, 2, 3, 11, 5, 10, 6}, From ac802f4e640f9391e77e4802095225e509b9072e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 09:33:09 +0330 Subject: [PATCH 257/775] Case 73 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b6f94f350..70ba2a1d4 100644 --- a/render/march3.go +++ b/render/march3.go @@ -505,6 +505,7 @@ var mcTriangleTable = [256][]int{ {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8}, // 0b01001000 case 72 {2, 3, 11, 10, 6, 5}, + // 0b01001001 case 73 {11, 0, 8, 11, 2, 0, 10, 6, 5}, {0, 1, 9, 2, 3, 11, 5, 10, 6}, {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11}, From 43be3c25e3ac1341ed328d48c0bf81b534f1d54b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 09:40:51 +0330 Subject: [PATCH 258/775] Case 74 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 70ba2a1d4..0c235616b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -507,6 +507,7 @@ var mcTriangleTable = [256][]int{ {2, 3, 11, 10, 6, 5}, // 0b01001001 case 73 {11, 0, 8, 11, 2, 0, 10, 6, 5}, + // 0b01001010 case 74 {0, 1, 9, 2, 3, 11, 5, 10, 6}, {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11}, {6, 3, 11, 6, 5, 3, 5, 1, 3}, From b08ed43627b0e910f222f409eb30256240200f14 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 09:48:25 +0330 Subject: [PATCH 259/775] Case 75 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 0c235616b..e75aa195b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -509,6 +509,7 @@ var mcTriangleTable = [256][]int{ {11, 0, 8, 11, 2, 0, 10, 6, 5}, // 0b01001010 case 74 {0, 1, 9, 2, 3, 11, 5, 10, 6}, + // 0b01001011 case 75 {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11}, {6, 3, 11, 6, 5, 3, 5, 1, 3}, {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6}, From 9720fc4fa8e2fbe9fac9f96c28079781aee5a451 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 09:58:09 +0330 Subject: [PATCH 260/775] Case 76 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e75aa195b..74eacf213 100644 --- a/render/march3.go +++ b/render/march3.go @@ -511,6 +511,7 @@ var mcTriangleTable = [256][]int{ {0, 1, 9, 2, 3, 11, 5, 10, 6}, // 0b01001011 case 75 {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11}, + // 0b01001100 case 76 {6, 3, 11, 6, 5, 3, 5, 1, 3}, {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6}, {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9}, From 57f5f6f1f0f2a35101cef983eca81dc2d8f243b9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 10:07:01 +0330 Subject: [PATCH 261/775] Case 77 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 74eacf213..27b21a1fd 100644 --- a/render/march3.go +++ b/render/march3.go @@ -513,6 +513,7 @@ var mcTriangleTable = [256][]int{ {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11}, // 0b01001100 case 76 {6, 3, 11, 6, 5, 3, 5, 1, 3}, + // 0b01001101 case 77 {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6}, {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9}, {6, 5, 9, 6, 9, 11, 11, 9, 8}, From ba4494700dbffd7ab2bcb7bcba675707ad562f5b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 18 May 2023 10:19:54 +0330 Subject: [PATCH 262/775] Case 78 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 27b21a1fd..02ae1d20a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -515,6 +515,7 @@ var mcTriangleTable = [256][]int{ {6, 3, 11, 6, 5, 3, 5, 1, 3}, // 0b01001101 case 77 {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6}, + // 0b01001110 case 78 {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9}, {6, 5, 9, 6, 9, 11, 11, 9, 8}, {5, 10, 6, 4, 7, 8}, From cbf78af44661b25f31f80151859fdfe0c2dbb8ef Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 10:44:42 +0330 Subject: [PATCH 263/775] Case 79 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 02ae1d20a..66f01ca71 100644 --- a/render/march3.go +++ b/render/march3.go @@ -517,6 +517,7 @@ var mcTriangleTable = [256][]int{ {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6}, // 0b01001110 case 78 {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9}, + // 0b01001111 case 79 {6, 5, 9, 6, 9, 11, 11, 9, 8}, {5, 10, 6, 4, 7, 8}, {4, 3, 0, 4, 7, 3, 6, 5, 10}, From ab85229212984ec0446bc2e1d518b4ee3144f180 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 11:10:39 +0330 Subject: [PATCH 264/775] Case 80 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 66f01ca71..920b058b3 100644 --- a/render/march3.go +++ b/render/march3.go @@ -519,6 +519,7 @@ var mcTriangleTable = [256][]int{ {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9}, // 0b01001111 case 79 {6, 5, 9, 6, 9, 11, 11, 9, 8}, + // 0b01010000 case 80 {5, 10, 6, 4, 7, 8}, {4, 3, 0, 4, 7, 3, 6, 5, 10}, {1, 9, 0, 5, 10, 6, 8, 4, 7}, From 4dd5396ba8110480bd6d304e4b347d879e2ff3d0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 11:17:09 +0330 Subject: [PATCH 265/775] Case 81 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 920b058b3..8c812c75b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -521,6 +521,7 @@ var mcTriangleTable = [256][]int{ {6, 5, 9, 6, 9, 11, 11, 9, 8}, // 0b01010000 case 80 {5, 10, 6, 4, 7, 8}, + // 0b01010001 case 81 {4, 3, 0, 4, 7, 3, 6, 5, 10}, {1, 9, 0, 5, 10, 6, 8, 4, 7}, {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4}, From a816b15c990e5529071e8d61a8131f1734a6b219 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 11:26:06 +0330 Subject: [PATCH 266/775] Case 82 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8c812c75b..96cef1b18 100644 --- a/render/march3.go +++ b/render/march3.go @@ -523,6 +523,7 @@ var mcTriangleTable = [256][]int{ {5, 10, 6, 4, 7, 8}, // 0b01010001 case 81 {4, 3, 0, 4, 7, 3, 6, 5, 10}, + // 0b01010010 case 82 {1, 9, 0, 5, 10, 6, 8, 4, 7}, {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4}, {6, 1, 2, 6, 5, 1, 4, 7, 8}, From 1a5fd351948c35df0fbcc3db7519c3bf6200e9a6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 11:38:30 +0330 Subject: [PATCH 267/775] Case 83 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 96cef1b18..8dec0e8fc 100644 --- a/render/march3.go +++ b/render/march3.go @@ -525,6 +525,7 @@ var mcTriangleTable = [256][]int{ {4, 3, 0, 4, 7, 3, 6, 5, 10}, // 0b01010010 case 82 {1, 9, 0, 5, 10, 6, 8, 4, 7}, + // 0b01010011 case 83 {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4}, {6, 1, 2, 6, 5, 1, 4, 7, 8}, {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7}, From 30f9874ffe665f7a1023436a99a9c769082a7533 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 11:47:01 +0330 Subject: [PATCH 268/775] Case 84 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8dec0e8fc..a655b5ecf 100644 --- a/render/march3.go +++ b/render/march3.go @@ -527,6 +527,7 @@ var mcTriangleTable = [256][]int{ {1, 9, 0, 5, 10, 6, 8, 4, 7}, // 0b01010011 case 83 {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4}, + // 0b01010100 case 84 {6, 1, 2, 6, 5, 1, 4, 7, 8}, {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7}, {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6}, From eaa8552790d886b26e5ca7acee27e39129965717 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 12:14:24 +0330 Subject: [PATCH 269/775] Case 85 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a655b5ecf..e01ca6564 100644 --- a/render/march3.go +++ b/render/march3.go @@ -529,6 +529,7 @@ var mcTriangleTable = [256][]int{ {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4}, // 0b01010100 case 84 {6, 1, 2, 6, 5, 1, 4, 7, 8}, + // 0b01010101 case 85 {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7}, {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6}, {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9}, From a3b01139f20880f4a991f32e437b70ec1cd60fdb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 12:20:52 +0330 Subject: [PATCH 270/775] Case 86 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e01ca6564..426306b86 100644 --- a/render/march3.go +++ b/render/march3.go @@ -531,6 +531,7 @@ var mcTriangleTable = [256][]int{ {6, 1, 2, 6, 5, 1, 4, 7, 8}, // 0b01010101 case 85 {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7}, + // 0b01010110 case 86 {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6}, {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9}, {3, 11, 2, 7, 8, 4, 10, 6, 5}, From fcce504086b39560e7eeb1968bf4bdcea4c78115 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 12:45:16 +0330 Subject: [PATCH 271/775] Case 87 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 426306b86..8edda875c 100644 --- a/render/march3.go +++ b/render/march3.go @@ -533,6 +533,7 @@ var mcTriangleTable = [256][]int{ {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7}, // 0b01010110 case 86 {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6}, + // 0b01010111 case 87 {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9}, {3, 11, 2, 7, 8, 4, 10, 6, 5}, {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11}, From 173bc696706bb2d713f965075b1b7f421df7b047 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 12:59:50 +0330 Subject: [PATCH 272/775] Case 88 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8edda875c..1ac4cdd16 100644 --- a/render/march3.go +++ b/render/march3.go @@ -535,6 +535,7 @@ var mcTriangleTable = [256][]int{ {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6}, // 0b01010111 case 87 {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9}, + // 0b01011000 case 88 {3, 11, 2, 7, 8, 4, 10, 6, 5}, {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11}, {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6}, From ad1e1d0b51020b279dafb95d3070e35943a274d4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 13:08:55 +0330 Subject: [PATCH 273/775] Case 89 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 1ac4cdd16..c8faec289 100644 --- a/render/march3.go +++ b/render/march3.go @@ -537,6 +537,7 @@ var mcTriangleTable = [256][]int{ {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9}, // 0b01011000 case 88 {3, 11, 2, 7, 8, 4, 10, 6, 5}, + // 0b01011001 case 89 {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11}, {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6}, {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6}, From ce2f6eb51bf3d7c87afb3200a841e6bd48a7293c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 13:19:56 +0330 Subject: [PATCH 274/775] Case 90 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index c8faec289..7b799347e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -539,6 +539,7 @@ var mcTriangleTable = [256][]int{ {3, 11, 2, 7, 8, 4, 10, 6, 5}, // 0b01011001 case 89 {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11}, + // 0b01011010 case 90 {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6}, {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6}, {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6}, From 4776b935ad5a09d5958ab7cc40638bde9b0ebe2b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 13:29:44 +0330 Subject: [PATCH 275/775] Case 91 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7b799347e..e080d9995 100644 --- a/render/march3.go +++ b/render/march3.go @@ -541,6 +541,7 @@ var mcTriangleTable = [256][]int{ {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11}, // 0b01011010 case 90 {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6}, + // 0b01011011 case 91 {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6}, {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6}, {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11}, From 67ddab76b8331f9ab4e2918fa03e7eeb976ff6c2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 13:44:49 +0330 Subject: [PATCH 276/775] Case 92 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e080d9995..845643ee9 100644 --- a/render/march3.go +++ b/render/march3.go @@ -543,6 +543,7 @@ var mcTriangleTable = [256][]int{ {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6}, // 0b01011011 case 91 {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6}, + // 0b01011100 case 92 {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6}, {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11}, {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7}, From 5028ad6da70237b5625e2c5eeae48b8df905874a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 13:56:18 +0330 Subject: [PATCH 277/775] Case 93 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 845643ee9..d68fa4680 100644 --- a/render/march3.go +++ b/render/march3.go @@ -545,6 +545,7 @@ var mcTriangleTable = [256][]int{ {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6}, // 0b01011100 case 92 {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6}, + // 0b01011101 case 93 {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11}, {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7}, {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9}, From 1a8ee492cc13a5ce02201396107aed29b1546645 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 14:07:47 +0330 Subject: [PATCH 278/775] Case 94 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d68fa4680..aae027bc0 100644 --- a/render/march3.go +++ b/render/march3.go @@ -547,6 +547,7 @@ var mcTriangleTable = [256][]int{ {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6}, // 0b01011101 case 93 {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11}, + // 0b01011110 case 94 {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7}, {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9}, {10, 4, 9, 6, 4, 10}, From 9b5064fdf461a9147edfd668e3145e2571302eb3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 14:20:25 +0330 Subject: [PATCH 279/775] Case 95 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index aae027bc0..a333b38e1 100644 --- a/render/march3.go +++ b/render/march3.go @@ -549,6 +549,7 @@ var mcTriangleTable = [256][]int{ {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11}, // 0b01011110 case 94 {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7}, + // 0b01011111 case 95 {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9}, {10, 4, 9, 6, 4, 10}, {4, 10, 6, 4, 9, 10, 0, 8, 3}, From 8a9b2137378a113e5e72422149e1db69136cd157 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 14:33:50 +0330 Subject: [PATCH 280/775] Case 96 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a333b38e1..7e5474301 100644 --- a/render/march3.go +++ b/render/march3.go @@ -551,6 +551,7 @@ var mcTriangleTable = [256][]int{ {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7}, // 0b01011111 case 95 {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9}, + // 0b01100000 case 96 {10, 4, 9, 6, 4, 10}, {4, 10, 6, 4, 9, 10, 0, 8, 3}, {10, 0, 1, 10, 6, 0, 6, 4, 0}, From cf014d0afe7c8720c6c64934c43bb9a6faddaeec Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 15:04:55 +0330 Subject: [PATCH 281/775] Case 97 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7e5474301..b79f9c36b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -553,6 +553,7 @@ var mcTriangleTable = [256][]int{ {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9}, // 0b01100000 case 96 {10, 4, 9, 6, 4, 10}, + // 0b01100001 case 97 {4, 10, 6, 4, 9, 10, 0, 8, 3}, {10, 0, 1, 10, 6, 0, 6, 4, 0}, {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10}, From cbbb2413e3de77ab5e87f3a11f2bd47e02ce2a45 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 15:11:00 +0330 Subject: [PATCH 282/775] Case 98 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b79f9c36b..fe065c4df 100644 --- a/render/march3.go +++ b/render/march3.go @@ -555,6 +555,7 @@ var mcTriangleTable = [256][]int{ {10, 4, 9, 6, 4, 10}, // 0b01100001 case 97 {4, 10, 6, 4, 9, 10, 0, 8, 3}, + // 0b01100010 case 98 {10, 0, 1, 10, 6, 0, 6, 4, 0}, {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10}, {1, 4, 9, 1, 2, 4, 2, 6, 4}, From 281b713eda9bef1c94bfed8f01d81a1975030a65 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 15:19:27 +0330 Subject: [PATCH 283/775] Case 99 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fe065c4df..6732cde17 100644 --- a/render/march3.go +++ b/render/march3.go @@ -557,6 +557,7 @@ var mcTriangleTable = [256][]int{ {4, 10, 6, 4, 9, 10, 0, 8, 3}, // 0b01100010 case 98 {10, 0, 1, 10, 6, 0, 6, 4, 0}, + // 0b01100011 case 99 {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10}, {1, 4, 9, 1, 2, 4, 2, 6, 4}, {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4}, From 7479eaf73d752cea44ad7d347400e35a2446b6d7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 15:33:40 +0330 Subject: [PATCH 284/775] Case 100 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 6732cde17..e4f852587 100644 --- a/render/march3.go +++ b/render/march3.go @@ -559,6 +559,7 @@ var mcTriangleTable = [256][]int{ {10, 0, 1, 10, 6, 0, 6, 4, 0}, // 0b01100011 case 99 {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10}, + // 0b01100100 case 100 {1, 4, 9, 1, 2, 4, 2, 6, 4}, {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4}, {0, 2, 4, 4, 2, 6}, From 069acbd26b2cda026dff045e2cf2632deff9d59d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 15:44:40 +0330 Subject: [PATCH 285/775] Case 101 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e4f852587..701d07607 100644 --- a/render/march3.go +++ b/render/march3.go @@ -561,6 +561,7 @@ var mcTriangleTable = [256][]int{ {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10}, // 0b01100100 case 100 {1, 4, 9, 1, 2, 4, 2, 6, 4}, + // 0b01100101 case 101 {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4}, {0, 2, 4, 4, 2, 6}, {8, 3, 2, 8, 2, 4, 4, 2, 6}, From de54a1772153af8fd912f5dd96fd71c4fce8214d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 16:02:04 +0330 Subject: [PATCH 286/775] Case 102 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 701d07607..0a74aca18 100644 --- a/render/march3.go +++ b/render/march3.go @@ -563,6 +563,7 @@ var mcTriangleTable = [256][]int{ {1, 4, 9, 1, 2, 4, 2, 6, 4}, // 0b01100101 case 101 {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4}, + // 0b01100110 case 102 {0, 2, 4, 4, 2, 6}, {8, 3, 2, 8, 2, 4, 4, 2, 6}, {10, 4, 9, 10, 6, 4, 11, 2, 3}, From dcd28b3c7af8dbe58b5a5bcc541cd23a8e58efd2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 16:18:10 +0330 Subject: [PATCH 287/775] Case 103 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 0a74aca18..cb00345c8 100644 --- a/render/march3.go +++ b/render/march3.go @@ -565,6 +565,7 @@ var mcTriangleTable = [256][]int{ {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4}, // 0b01100110 case 102 {0, 2, 4, 4, 2, 6}, + // 0b01100111 case 103 {8, 3, 2, 8, 2, 4, 4, 2, 6}, {10, 4, 9, 10, 6, 4, 11, 2, 3}, {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6}, From c5b9e1ef55bd66e330df4f0d8b4ae8ce44ca643e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 16:30:37 +0330 Subject: [PATCH 288/775] Case 104 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index cb00345c8..fef61d1e0 100644 --- a/render/march3.go +++ b/render/march3.go @@ -567,6 +567,7 @@ var mcTriangleTable = [256][]int{ {0, 2, 4, 4, 2, 6}, // 0b01100111 case 103 {8, 3, 2, 8, 2, 4, 4, 2, 6}, + // 0b01101000 case 104 {10, 4, 9, 10, 6, 4, 11, 2, 3}, {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6}, {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10}, From 3d8ca0aaffe66931dc8ff04efa79334e7677a932 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 16:39:28 +0330 Subject: [PATCH 289/775] Case 105 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fef61d1e0..56563564d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -569,6 +569,7 @@ var mcTriangleTable = [256][]int{ {8, 3, 2, 8, 2, 4, 4, 2, 6}, // 0b01101000 case 104 {10, 4, 9, 10, 6, 4, 11, 2, 3}, + // 0b01101001 case 105 {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6}, {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10}, {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1}, From 13cbb4d3082bb3998e2115af721eccbe5757f38c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 16:47:24 +0330 Subject: [PATCH 290/775] Case 106 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 56563564d..2cd469443 100644 --- a/render/march3.go +++ b/render/march3.go @@ -571,6 +571,7 @@ var mcTriangleTable = [256][]int{ {10, 4, 9, 10, 6, 4, 11, 2, 3}, // 0b01101001 case 105 {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6}, + // 0b01101010 case 106 {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10}, {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1}, {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3}, From 3b2a182fc8d4d1cb0e736785254f1d8181c21d90 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 16:56:42 +0330 Subject: [PATCH 291/775] Case 107 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 2cd469443..6e13d947e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -573,6 +573,7 @@ var mcTriangleTable = [256][]int{ {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6}, // 0b01101010 case 106 {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10}, + // 0b01101011 case 107 {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1}, {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3}, {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1}, From ad105ac3b7684290ee3552f6677a0482dc727e10 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 20 May 2023 17:10:10 +0330 Subject: [PATCH 292/775] Case 108 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 6e13d947e..da78cf3f4 100644 --- a/render/march3.go +++ b/render/march3.go @@ -575,6 +575,7 @@ var mcTriangleTable = [256][]int{ {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10}, // 0b01101011 case 107 {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1}, + // 0b01101100 case 108 {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3}, {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1}, {3, 11, 6, 3, 6, 0, 0, 6, 4}, From 8c71f3e39b234ecff51c8296045c739312c6a114 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 09:18:12 +0330 Subject: [PATCH 293/775] Case 109 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index da78cf3f4..7c082c066 100644 --- a/render/march3.go +++ b/render/march3.go @@ -577,6 +577,7 @@ var mcTriangleTable = [256][]int{ {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1}, // 0b01101100 case 108 {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3}, + // 0b01101101 case 109 {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1}, {3, 11, 6, 3, 6, 0, 0, 6, 4}, {6, 4, 8, 11, 6, 8}, From d62ea2888487aa1320b5138e1d7a90db10e62f01 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 09:31:31 +0330 Subject: [PATCH 294/775] Case 110 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7c082c066..9d7a90598 100644 --- a/render/march3.go +++ b/render/march3.go @@ -579,6 +579,7 @@ var mcTriangleTable = [256][]int{ {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3}, // 0b01101101 case 109 {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1}, + // 0b01101110 case 110 {3, 11, 6, 3, 6, 0, 0, 6, 4}, {6, 4, 8, 11, 6, 8}, {7, 10, 6, 7, 8, 10, 8, 9, 10}, From 360a3f94d5f0389bf383f483c2831178e5a1b68f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 09:44:06 +0330 Subject: [PATCH 295/775] Case 111 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9d7a90598..4c9a48a65 100644 --- a/render/march3.go +++ b/render/march3.go @@ -581,6 +581,7 @@ var mcTriangleTable = [256][]int{ {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1}, // 0b01101110 case 110 {3, 11, 6, 3, 6, 0, 0, 6, 4}, + // 0b01101111 case 111 {6, 4, 8, 11, 6, 8}, {7, 10, 6, 7, 8, 10, 8, 9, 10}, {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10}, From 1978e1f62d28f697c61decd1ef0f06c84ccdfb5f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 10:28:29 +0330 Subject: [PATCH 296/775] Case 112 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 4c9a48a65..2d6721173 100644 --- a/render/march3.go +++ b/render/march3.go @@ -583,6 +583,7 @@ var mcTriangleTable = [256][]int{ {3, 11, 6, 3, 6, 0, 0, 6, 4}, // 0b01101111 case 111 {6, 4, 8, 11, 6, 8}, + // 0b01110000 case 112 {7, 10, 6, 7, 8, 10, 8, 9, 10}, {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10}, {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0}, From 2b08cbb159a78a703f938cca516a3157a29ead5e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 10:39:55 +0330 Subject: [PATCH 297/775] Case 113 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 2d6721173..c4d6741ec 100644 --- a/render/march3.go +++ b/render/march3.go @@ -585,6 +585,7 @@ var mcTriangleTable = [256][]int{ {6, 4, 8, 11, 6, 8}, // 0b01110000 case 112 {7, 10, 6, 7, 8, 10, 8, 9, 10}, + // 0b01110001 case 113 {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10}, {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0}, {10, 6, 7, 10, 7, 1, 1, 7, 3}, From f868e9b7d522f8603407c4c86cfe02702a78678a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 10:56:51 +0330 Subject: [PATCH 298/775] Case 114 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index c4d6741ec..25a394de8 100644 --- a/render/march3.go +++ b/render/march3.go @@ -587,6 +587,7 @@ var mcTriangleTable = [256][]int{ {7, 10, 6, 7, 8, 10, 8, 9, 10}, // 0b01110001 case 113 {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10}, + // 0b01110010 case 114 {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0}, {10, 6, 7, 10, 7, 1, 1, 7, 3}, {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7}, From b6431f98123d2e43b8dba72af3c12eb0ec8a2688 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 11:10:53 +0330 Subject: [PATCH 299/775] Case 115 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 25a394de8..e985bf312 100644 --- a/render/march3.go +++ b/render/march3.go @@ -589,6 +589,7 @@ var mcTriangleTable = [256][]int{ {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10}, // 0b01110010 case 114 {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0}, + // 0b01110011 case 115 {10, 6, 7, 10, 7, 1, 1, 7, 3}, {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7}, {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9}, From 9a6c36d0a1ec14d603a055123311a3b72c8dec3c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 11:13:55 +0330 Subject: [PATCH 300/775] Case 116 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e985bf312..a433fa284 100644 --- a/render/march3.go +++ b/render/march3.go @@ -591,6 +591,7 @@ var mcTriangleTable = [256][]int{ {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0}, // 0b01110011 case 115 {10, 6, 7, 10, 7, 1, 1, 7, 3}, + // 0b01110100 case 116 {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7}, {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9}, {7, 8, 0, 7, 0, 6, 6, 0, 2}, From 21dd3ccc3d5558a81529df160369c2ae168e4f67 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 11:41:07 +0330 Subject: [PATCH 301/775] Case 117 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a433fa284..93142b0a6 100644 --- a/render/march3.go +++ b/render/march3.go @@ -593,6 +593,7 @@ var mcTriangleTable = [256][]int{ {10, 6, 7, 10, 7, 1, 1, 7, 3}, // 0b01110100 case 116 {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7}, + // 0b01110101 case 117 {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9}, {7, 8, 0, 7, 0, 6, 6, 0, 2}, {7, 3, 2, 6, 7, 2}, From f3ab0fcbee8b42f7edab81a368a7e2cb0645f088 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 11:57:32 +0330 Subject: [PATCH 302/775] Case 118 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 93142b0a6..b70feaae8 100644 --- a/render/march3.go +++ b/render/march3.go @@ -595,6 +595,7 @@ var mcTriangleTable = [256][]int{ {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7}, // 0b01110101 case 117 {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9}, + // 0b01110110 case 118 {7, 8, 0, 7, 0, 6, 6, 0, 2}, {7, 3, 2, 6, 7, 2}, {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7}, From 4f402546cdbf5db1d7403bc6985c0a3e828d9812 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 12:09:35 +0330 Subject: [PATCH 303/775] Case 119 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b70feaae8..9e4595b07 100644 --- a/render/march3.go +++ b/render/march3.go @@ -597,6 +597,7 @@ var mcTriangleTable = [256][]int{ {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9}, // 0b01110110 case 118 {7, 8, 0, 7, 0, 6, 6, 0, 2}, + // 0b01110111 case 119 {7, 3, 2, 6, 7, 2}, {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7}, {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7}, From 2bffcb30d789e8b09e58c20d30d4825655513a99 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 12:24:45 +0330 Subject: [PATCH 304/775] Case 120 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9e4595b07..65dc95217 100644 --- a/render/march3.go +++ b/render/march3.go @@ -599,6 +599,7 @@ var mcTriangleTable = [256][]int{ {7, 8, 0, 7, 0, 6, 6, 0, 2}, // 0b01110111 case 119 {7, 3, 2, 6, 7, 2}, + // 0b01111000 case 120 {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7}, {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7}, {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11}, From 759e4f7c24efb4da4ffd22f3bba23a6a1463fba3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 16:07:04 +0330 Subject: [PATCH 305/775] Case 121 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 65dc95217..fcfe69afc 100644 --- a/render/march3.go +++ b/render/march3.go @@ -601,6 +601,7 @@ var mcTriangleTable = [256][]int{ {7, 3, 2, 6, 7, 2}, // 0b01111000 case 120 {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7}, + // 0b01111001 case 121 {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7}, {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11}, {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1}, From 0005835be02933a6e2aefa2676abed5e20a4edb2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 16:31:11 +0330 Subject: [PATCH 306/775] Case 122 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fcfe69afc..f78490a37 100644 --- a/render/march3.go +++ b/render/march3.go @@ -603,6 +603,7 @@ var mcTriangleTable = [256][]int{ {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7}, // 0b01111001 case 121 {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7}, + // 0b01111010 case 122 {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11}, {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1}, {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6}, From 09b2d24b906748d755f324cff6b8f83eee4fa1d8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 17:03:02 +0330 Subject: [PATCH 307/775] Case 123 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index f78490a37..6aeec22c0 100644 --- a/render/march3.go +++ b/render/march3.go @@ -605,6 +605,7 @@ var mcTriangleTable = [256][]int{ {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7}, // 0b01111010 case 122 {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11}, + // 0b01111011 case 123 {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1}, {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6}, {0, 9, 1, 11, 6, 7}, From 90b5dd0f1d49e220e9e50c7f9e3488fb23f4b5e9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 17:16:36 +0330 Subject: [PATCH 308/775] Case 124 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 6aeec22c0..92b00f60a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -607,6 +607,7 @@ var mcTriangleTable = [256][]int{ {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11}, // 0b01111011 case 123 {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1}, + // 0b01111100 case 124 {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6}, {0, 9, 1, 11, 6, 7}, {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0}, From a594d54dd2822c32cce9adca7a1bffcae51cf11f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 17:29:52 +0330 Subject: [PATCH 309/775] Case 125 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 92b00f60a..25cefcce3 100644 --- a/render/march3.go +++ b/render/march3.go @@ -609,6 +609,7 @@ var mcTriangleTable = [256][]int{ {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1}, // 0b01111100 case 124 {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6}, + // 0b01111101 case 125 {0, 9, 1, 11, 6, 7}, {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0}, {7, 11, 6}, From 26ab9f71c6a6c050f04baeaac7686b56aad4c43c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 17:44:39 +0330 Subject: [PATCH 310/775] Case 126 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 25cefcce3..5bf4b1466 100644 --- a/render/march3.go +++ b/render/march3.go @@ -611,6 +611,7 @@ var mcTriangleTable = [256][]int{ {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6}, // 0b01111101 case 125 {0, 9, 1, 11, 6, 7}, + // 0b01111110 case 126 {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0}, {7, 11, 6}, {7, 6, 11}, From b1b9ab0797ec6610f0a969664d58faa16a6b7403 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 17:54:48 +0330 Subject: [PATCH 311/775] Case 127 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 5bf4b1466..fb0902b2a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -613,6 +613,7 @@ var mcTriangleTable = [256][]int{ {0, 9, 1, 11, 6, 7}, // 0b01111110 case 126 {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0}, + // 0b01111111 case 127 {7, 11, 6}, {7, 6, 11}, {3, 0, 8, 11, 7, 6}, From 9e336ca41c1091d0fde4629b2d2466ab9510de19 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 21 May 2023 18:08:27 +0330 Subject: [PATCH 312/775] Case 128 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fb0902b2a..84320a52f 100644 --- a/render/march3.go +++ b/render/march3.go @@ -615,6 +615,7 @@ var mcTriangleTable = [256][]int{ {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0}, // 0b01111111 case 127 {7, 11, 6}, + // 0b10000000 case 128 {7, 6, 11}, {3, 0, 8, 11, 7, 6}, {0, 1, 9, 11, 7, 6}, From c943bc8d887284d13d184a2c77ab0fa3db2c78ea Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 09:15:17 +0330 Subject: [PATCH 313/775] Case 129 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 84320a52f..b6f0cce92 100644 --- a/render/march3.go +++ b/render/march3.go @@ -617,6 +617,7 @@ var mcTriangleTable = [256][]int{ {7, 11, 6}, // 0b10000000 case 128 {7, 6, 11}, + // 0b10000001 case 129 {3, 0, 8, 11, 7, 6}, {0, 1, 9, 11, 7, 6}, {8, 1, 9, 8, 3, 1, 11, 7, 6}, From 6fb178a94aee264074daf31cbc1d7ea88c1d111e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 09:24:41 +0330 Subject: [PATCH 314/775] Case 130 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b6f0cce92..4bb91b66e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -619,6 +619,7 @@ var mcTriangleTable = [256][]int{ {7, 6, 11}, // 0b10000001 case 129 {3, 0, 8, 11, 7, 6}, + // 0b10000010 case 130 {0, 1, 9, 11, 7, 6}, {8, 1, 9, 8, 3, 1, 11, 7, 6}, {10, 1, 2, 6, 11, 7}, From 4f0379b882eaefd2b0fdf7232030fd0df8fe0cb4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 09:29:36 +0330 Subject: [PATCH 315/775] Case 131 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 4bb91b66e..c6458782a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -622,6 +622,7 @@ var mcTriangleTable = [256][]int{ // 0b10000010 case 130 {0, 1, 9, 11, 7, 6}, {8, 1, 9, 8, 3, 1, 11, 7, 6}, + // 0b10000011 case 131 {10, 1, 2, 6, 11, 7}, {1, 2, 10, 3, 0, 8, 6, 11, 7}, {2, 9, 0, 2, 10, 9, 6, 11, 7}, From 1f24073b8829824d16bf3986c024b081f9374ef4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 09:32:31 +0330 Subject: [PATCH 316/775] Fix case 131 --- render/march3.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/march3.go b/render/march3.go index c6458782a..c171ed95e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -621,8 +621,8 @@ var mcTriangleTable = [256][]int{ {3, 0, 8, 11, 7, 6}, // 0b10000010 case 130 {0, 1, 9, 11, 7, 6}, - {8, 1, 9, 8, 3, 1, 11, 7, 6}, // 0b10000011 case 131 + {8, 1, 9, 8, 3, 1, 11, 7, 6}, {10, 1, 2, 6, 11, 7}, {1, 2, 10, 3, 0, 8, 6, 11, 7}, {2, 9, 0, 2, 10, 9, 6, 11, 7}, From 324ab23bd6d8c14a180ce454ce3415081d88e45c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 09:42:27 +0330 Subject: [PATCH 317/775] Case 132 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index c171ed95e..665b9f465 100644 --- a/render/march3.go +++ b/render/march3.go @@ -623,6 +623,7 @@ var mcTriangleTable = [256][]int{ {0, 1, 9, 11, 7, 6}, // 0b10000011 case 131 {8, 1, 9, 8, 3, 1, 11, 7, 6}, + // 0b10000100 case 132 {10, 1, 2, 6, 11, 7}, {1, 2, 10, 3, 0, 8, 6, 11, 7}, {2, 9, 0, 2, 10, 9, 6, 11, 7}, From 0293e2dcabbfe43463ba36791184ec1c0bf5443e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 09:50:25 +0330 Subject: [PATCH 318/775] Case 133 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 665b9f465..146fe7d2d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -625,6 +625,7 @@ var mcTriangleTable = [256][]int{ {8, 1, 9, 8, 3, 1, 11, 7, 6}, // 0b10000100 case 132 {10, 1, 2, 6, 11, 7}, + // 0b10000101 case 133 {1, 2, 10, 3, 0, 8, 6, 11, 7}, {2, 9, 0, 2, 10, 9, 6, 11, 7}, {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8}, From fca91f2913bc8a5035cb80c3d3c26d8b5e128e73 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 09:57:21 +0330 Subject: [PATCH 319/775] Case 134 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 146fe7d2d..252ab0f68 100644 --- a/render/march3.go +++ b/render/march3.go @@ -627,6 +627,7 @@ var mcTriangleTable = [256][]int{ {10, 1, 2, 6, 11, 7}, // 0b10000101 case 133 {1, 2, 10, 3, 0, 8, 6, 11, 7}, + // 0b10000110 case 134 {2, 9, 0, 2, 10, 9, 6, 11, 7}, {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8}, {7, 2, 3, 6, 2, 7}, From e3a7a2a0f70b190a25a094c50b0efab3acc0e437 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 10:05:29 +0330 Subject: [PATCH 320/775] Case 135 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 252ab0f68..fb0b01869 100644 --- a/render/march3.go +++ b/render/march3.go @@ -629,6 +629,7 @@ var mcTriangleTable = [256][]int{ {1, 2, 10, 3, 0, 8, 6, 11, 7}, // 0b10000110 case 134 {2, 9, 0, 2, 10, 9, 6, 11, 7}, + // 0b10000111 case 135 {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8}, {7, 2, 3, 6, 2, 7}, {7, 0, 8, 7, 6, 0, 6, 2, 0}, From fae083255087d3b650266529fde3234bfa8cd239 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 10:13:51 +0330 Subject: [PATCH 321/775] Case 136 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fb0b01869..1092ba17d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -631,6 +631,7 @@ var mcTriangleTable = [256][]int{ {2, 9, 0, 2, 10, 9, 6, 11, 7}, // 0b10000111 case 135 {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8}, + // 0b10001000 case 136 {7, 2, 3, 6, 2, 7}, {7, 0, 8, 7, 6, 0, 6, 2, 0}, {2, 7, 6, 2, 3, 7, 0, 1, 9}, From 84122a8f0d9980cb8cb22c72965ae86c19653190 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 10:20:15 +0330 Subject: [PATCH 322/775] Case 137 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 1092ba17d..f67d552bf 100644 --- a/render/march3.go +++ b/render/march3.go @@ -633,6 +633,7 @@ var mcTriangleTable = [256][]int{ {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8}, // 0b10001000 case 136 {7, 2, 3, 6, 2, 7}, + // 0b10001001 case 137 {7, 0, 8, 7, 6, 0, 6, 2, 0}, {2, 7, 6, 2, 3, 7, 0, 1, 9}, {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6}, From 7d14f26553ac61048ac8acc4f2a763c8439467eb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 10:42:25 +0330 Subject: [PATCH 323/775] Case 138 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index f67d552bf..0855144a4 100644 --- a/render/march3.go +++ b/render/march3.go @@ -635,6 +635,7 @@ var mcTriangleTable = [256][]int{ {7, 2, 3, 6, 2, 7}, // 0b10001001 case 137 {7, 0, 8, 7, 6, 0, 6, 2, 0}, + // 0b10001010 case 138 {2, 7, 6, 2, 3, 7, 0, 1, 9}, {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6}, {10, 7, 6, 10, 1, 7, 1, 3, 7}, From 9421c8bf249096dd2f351064fe3ca5454480033a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 10:50:19 +0330 Subject: [PATCH 324/775] Case 139 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 0855144a4..740cbf680 100644 --- a/render/march3.go +++ b/render/march3.go @@ -637,6 +637,7 @@ var mcTriangleTable = [256][]int{ {7, 0, 8, 7, 6, 0, 6, 2, 0}, // 0b10001010 case 138 {2, 7, 6, 2, 3, 7, 0, 1, 9}, + // 0b10001011 case 139 {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6}, {10, 7, 6, 10, 1, 7, 1, 3, 7}, {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8}, From 76ddfc2cb37661cf53d283ff6ed357240265768e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 11:02:38 +0330 Subject: [PATCH 325/775] Case 140 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 740cbf680..8d04ddbe8 100644 --- a/render/march3.go +++ b/render/march3.go @@ -639,6 +639,7 @@ var mcTriangleTable = [256][]int{ {2, 7, 6, 2, 3, 7, 0, 1, 9}, // 0b10001011 case 139 {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6}, + // 0b10001100 case 140 {10, 7, 6, 10, 1, 7, 1, 3, 7}, {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8}, {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7}, From 1ac73a9d80342205454b812a5be35af80dc38f88 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 11:12:11 +0330 Subject: [PATCH 326/775] Case 141 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8d04ddbe8..5c6a87fc7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -641,6 +641,7 @@ var mcTriangleTable = [256][]int{ {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6}, // 0b10001100 case 140 {10, 7, 6, 10, 1, 7, 1, 3, 7}, + // 0b10001101 case 141 {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8}, {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7}, {7, 6, 10, 7, 10, 8, 8, 10, 9}, From d1eaf56e455d544d3753f622b31349a7efce2248 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 11:26:06 +0330 Subject: [PATCH 327/775] Case 142 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 5c6a87fc7..bcbd3f585 100644 --- a/render/march3.go +++ b/render/march3.go @@ -643,6 +643,7 @@ var mcTriangleTable = [256][]int{ {10, 7, 6, 10, 1, 7, 1, 3, 7}, // 0b10001101 case 141 {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8}, + // 0b10001110 case 142 {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7}, {7, 6, 10, 7, 10, 8, 8, 10, 9}, {6, 8, 4, 11, 8, 6}, From bbe83a1c427963954cfa79b3e72d55972e5682fd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 11:36:05 +0330 Subject: [PATCH 328/775] Case 143 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index bcbd3f585..a24178d16 100644 --- a/render/march3.go +++ b/render/march3.go @@ -645,6 +645,7 @@ var mcTriangleTable = [256][]int{ {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8}, // 0b10001110 case 142 {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7}, + // 0b10001111 case 143 {7, 6, 10, 7, 10, 8, 8, 10, 9}, {6, 8, 4, 11, 8, 6}, {3, 6, 11, 3, 0, 6, 0, 4, 6}, From 4bb8df73950eb4c124cf37f8d0a3d6baaf2761da Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 12:16:02 +0330 Subject: [PATCH 329/775] Case 144 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a24178d16..86d58162a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -647,6 +647,7 @@ var mcTriangleTable = [256][]int{ {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7}, // 0b10001111 case 143 {7, 6, 10, 7, 10, 8, 8, 10, 9}, + // 0b10010000 case 144 {6, 8, 4, 11, 8, 6}, {3, 6, 11, 3, 0, 6, 0, 4, 6}, {8, 6, 11, 8, 4, 6, 9, 0, 1}, From 18496efe8a2cd0f08552c1013b6dfe94f129da7c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 13:20:05 +0330 Subject: [PATCH 330/775] Case 145 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 86d58162a..57a83a6bc 100644 --- a/render/march3.go +++ b/render/march3.go @@ -649,6 +649,7 @@ var mcTriangleTable = [256][]int{ {7, 6, 10, 7, 10, 8, 8, 10, 9}, // 0b10010000 case 144 {6, 8, 4, 11, 8, 6}, + // 0b10010001 case 145 {3, 6, 11, 3, 0, 6, 0, 4, 6}, {8, 6, 11, 8, 4, 6, 9, 0, 1}, {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6}, From 781475e31eb6a60ed8b38f8161c71e889bb6133a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 13:34:47 +0330 Subject: [PATCH 331/775] Case 146 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 57a83a6bc..dd8fc0263 100644 --- a/render/march3.go +++ b/render/march3.go @@ -651,6 +651,7 @@ var mcTriangleTable = [256][]int{ {6, 8, 4, 11, 8, 6}, // 0b10010001 case 145 {3, 6, 11, 3, 0, 6, 0, 4, 6}, + // 0b10010010 case 146 {8, 6, 11, 8, 4, 6, 9, 0, 1}, {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6}, {6, 8, 4, 6, 11, 8, 2, 10, 1}, From 662b944e5a300605b944adf6ebf73d27b01df243 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 13:46:01 +0330 Subject: [PATCH 332/775] Case 147 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index dd8fc0263..1693a3831 100644 --- a/render/march3.go +++ b/render/march3.go @@ -653,6 +653,7 @@ var mcTriangleTable = [256][]int{ {3, 6, 11, 3, 0, 6, 0, 4, 6}, // 0b10010010 case 146 {8, 6, 11, 8, 4, 6, 9, 0, 1}, + // 0b10010011 case 147 {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6}, {6, 8, 4, 6, 11, 8, 2, 10, 1}, {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6}, From b2900373d5fdafa5dcb024d35c25f0d5a080167a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 14:03:42 +0330 Subject: [PATCH 333/775] Case 148 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 1693a3831..ec67175ad 100644 --- a/render/march3.go +++ b/render/march3.go @@ -655,6 +655,7 @@ var mcTriangleTable = [256][]int{ {8, 6, 11, 8, 4, 6, 9, 0, 1}, // 0b10010011 case 147 {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6}, + // 0b10010100 case 148 {6, 8, 4, 6, 11, 8, 2, 10, 1}, {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6}, {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9}, From b1d9c2cf0dedd7065594676424a9a6a564c390f3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 14:19:41 +0330 Subject: [PATCH 334/775] Case 149 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ec67175ad..998b4f0dc 100644 --- a/render/march3.go +++ b/render/march3.go @@ -657,6 +657,7 @@ var mcTriangleTable = [256][]int{ {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6}, // 0b10010100 case 148 {6, 8, 4, 6, 11, 8, 2, 10, 1}, + // 0b10010101 case 149 {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6}, {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9}, {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3}, From ff5c277329f89fc0e9cb64187c918625e05fe4c0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 14:35:34 +0330 Subject: [PATCH 335/775] Case 150 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 998b4f0dc..d2ab40161 100644 --- a/render/march3.go +++ b/render/march3.go @@ -659,6 +659,7 @@ var mcTriangleTable = [256][]int{ {6, 8, 4, 6, 11, 8, 2, 10, 1}, // 0b10010101 case 149 {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6}, + // 0b10010110 case 150 {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9}, {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3}, {8, 2, 3, 8, 4, 2, 4, 6, 2}, From 382f0e176006354a49177e8f8bcfac1c69720be8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 14:49:43 +0330 Subject: [PATCH 336/775] Case 151 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d2ab40161..3ef799ebc 100644 --- a/render/march3.go +++ b/render/march3.go @@ -661,6 +661,7 @@ var mcTriangleTable = [256][]int{ {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6}, // 0b10010110 case 150 {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9}, + // 0b10010111 case 151 {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3}, {8, 2, 3, 8, 4, 2, 4, 6, 2}, {0, 4, 2, 4, 6, 2}, From 398697f53f8d40f0b6ec8e5881a6af9f722e3f5b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 15:14:56 +0330 Subject: [PATCH 337/775] Case 152 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 3ef799ebc..675982ae2 100644 --- a/render/march3.go +++ b/render/march3.go @@ -663,6 +663,7 @@ var mcTriangleTable = [256][]int{ {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9}, // 0b10010111 case 151 {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3}, + // 0b10011000 case 152 {8, 2, 3, 8, 4, 2, 4, 6, 2}, {0, 4, 2, 4, 6, 2}, {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8}, From a189bd89cc2d86b79bf454da889d30fad1edbbbb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 15:31:55 +0330 Subject: [PATCH 338/775] Case 153 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 675982ae2..a8ca83770 100644 --- a/render/march3.go +++ b/render/march3.go @@ -665,6 +665,7 @@ var mcTriangleTable = [256][]int{ {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3}, // 0b10011000 case 152 {8, 2, 3, 8, 4, 2, 4, 6, 2}, + // 0b10011001 case 153 {0, 4, 2, 4, 6, 2}, {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8}, {1, 9, 4, 1, 4, 2, 2, 4, 6}, From de7562a7eb234ebdd43d0890c732f1e95a048de7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 16:30:13 +0330 Subject: [PATCH 339/775] Case 154 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a8ca83770..d16ae854b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -667,6 +667,7 @@ var mcTriangleTable = [256][]int{ {8, 2, 3, 8, 4, 2, 4, 6, 2}, // 0b10011001 case 153 {0, 4, 2, 4, 6, 2}, + // 0b10011010 case 154 {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8}, {1, 9, 4, 1, 4, 2, 2, 4, 6}, {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1}, From 7276957928427bd3c97e3ef1dc1afa063a8cb058 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 16:38:55 +0330 Subject: [PATCH 340/775] Case 155 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d16ae854b..c62546ddd 100644 --- a/render/march3.go +++ b/render/march3.go @@ -669,6 +669,7 @@ var mcTriangleTable = [256][]int{ {0, 4, 2, 4, 6, 2}, // 0b10011010 case 154 {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8}, + // 0b10011011 case 155 {1, 9, 4, 1, 4, 2, 2, 4, 6}, {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1}, {10, 1, 0, 10, 0, 6, 6, 0, 4}, From fe64b524566fc67f90f0cb336a7b281ac9884a10 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 16:48:11 +0330 Subject: [PATCH 341/775] Case 156 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index c62546ddd..3d3d899f1 100644 --- a/render/march3.go +++ b/render/march3.go @@ -671,6 +671,7 @@ var mcTriangleTable = [256][]int{ {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8}, // 0b10011011 case 155 {1, 9, 4, 1, 4, 2, 2, 4, 6}, + // 0b10011100 case 156 {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1}, {10, 1, 0, 10, 0, 6, 6, 0, 4}, {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3}, From 7ced94b5d401c40129a86ca82d3984b30d0fa9ba Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 16:59:47 +0330 Subject: [PATCH 342/775] Case 157 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 3d3d899f1..ee9e3a0ea 100644 --- a/render/march3.go +++ b/render/march3.go @@ -673,6 +673,7 @@ var mcTriangleTable = [256][]int{ {1, 9, 4, 1, 4, 2, 2, 4, 6}, // 0b10011100 case 156 {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1}, + // 0b10011101 case 157 {10, 1, 0, 10, 0, 6, 6, 0, 4}, {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3}, {10, 9, 4, 6, 10, 4}, From 0abb7c7ea417a7f742f1429bdb19fa4e73c2a4e0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 22 May 2023 17:11:31 +0330 Subject: [PATCH 343/775] Case 158 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ee9e3a0ea..064092b92 100644 --- a/render/march3.go +++ b/render/march3.go @@ -675,6 +675,7 @@ var mcTriangleTable = [256][]int{ {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1}, // 0b10011101 case 157 {10, 1, 0, 10, 0, 6, 6, 0, 4}, + // 0b10011110 case 158 {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3}, {10, 9, 4, 6, 10, 4}, {4, 9, 5, 7, 6, 11}, From 3dda1b169574cc29bd8c11a4eebef317a453604d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 09:39:58 +0330 Subject: [PATCH 344/775] Case 159 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 064092b92..ad68023ed 100644 --- a/render/march3.go +++ b/render/march3.go @@ -677,6 +677,7 @@ var mcTriangleTable = [256][]int{ {10, 1, 0, 10, 0, 6, 6, 0, 4}, // 0b10011110 case 158 {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3}, + // 0b10011111 case 159 {10, 9, 4, 6, 10, 4}, {4, 9, 5, 7, 6, 11}, {0, 8, 3, 4, 9, 5, 11, 7, 6}, From 80533b0412aa633f5093df4048837b91b01c94d3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 10:20:29 +0330 Subject: [PATCH 345/775] Case 160 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ad68023ed..3747d86d7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -679,6 +679,7 @@ var mcTriangleTable = [256][]int{ {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3}, // 0b10011111 case 159 {10, 9, 4, 6, 10, 4}, + // 0b10100000 case 160 {4, 9, 5, 7, 6, 11}, {0, 8, 3, 4, 9, 5, 11, 7, 6}, {5, 0, 1, 5, 4, 0, 7, 6, 11}, From 01a08e0a39dd8df149c9869fb40c7c91d363e6e3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 10:36:40 +0330 Subject: [PATCH 346/775] Case 161 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 3747d86d7..e76e20bfc 100644 --- a/render/march3.go +++ b/render/march3.go @@ -681,6 +681,7 @@ var mcTriangleTable = [256][]int{ {10, 9, 4, 6, 10, 4}, // 0b10100000 case 160 {4, 9, 5, 7, 6, 11}, + // 0b10100001 case 161 {0, 8, 3, 4, 9, 5, 11, 7, 6}, {5, 0, 1, 5, 4, 0, 7, 6, 11}, {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5}, From b5afee0463a53330abb9fa006070d08cf464e1cd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 10:46:04 +0330 Subject: [PATCH 347/775] Case 162 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e76e20bfc..ed0b01fbf 100644 --- a/render/march3.go +++ b/render/march3.go @@ -683,6 +683,7 @@ var mcTriangleTable = [256][]int{ {4, 9, 5, 7, 6, 11}, // 0b10100001 case 161 {0, 8, 3, 4, 9, 5, 11, 7, 6}, + // 0b10100010 case 162 {5, 0, 1, 5, 4, 0, 7, 6, 11}, {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5}, {9, 5, 4, 10, 1, 2, 7, 6, 11}, From b0a0804add9da92524bd3c1a685238a8221bdece Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 10:55:08 +0330 Subject: [PATCH 348/775] Case 163 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ed0b01fbf..c2df48ef1 100644 --- a/render/march3.go +++ b/render/march3.go @@ -685,6 +685,7 @@ var mcTriangleTable = [256][]int{ {0, 8, 3, 4, 9, 5, 11, 7, 6}, // 0b10100010 case 162 {5, 0, 1, 5, 4, 0, 7, 6, 11}, + // 0b10100011 case 163 {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5}, {9, 5, 4, 10, 1, 2, 7, 6, 11}, {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5}, From 310a32524e08089044aba55dcea5b0e64466c12f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 11:15:16 +0330 Subject: [PATCH 349/775] Case 164 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index c2df48ef1..fe25ba242 100644 --- a/render/march3.go +++ b/render/march3.go @@ -687,6 +687,7 @@ var mcTriangleTable = [256][]int{ {5, 0, 1, 5, 4, 0, 7, 6, 11}, // 0b10100011 case 163 {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5}, + // 0b10100100 case 164 {9, 5, 4, 10, 1, 2, 7, 6, 11}, {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5}, {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2}, From 700321213eff8df0f0cd6defeb8c7360d1e984fd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 11:30:45 +0330 Subject: [PATCH 350/775] Case 165 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fe25ba242..5c153293b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -689,6 +689,7 @@ var mcTriangleTable = [256][]int{ {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5}, // 0b10100100 case 164 {9, 5, 4, 10, 1, 2, 7, 6, 11}, + // 0b10100101 case 165 {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5}, {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2}, {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6}, From fabd6a76e0ec3f3f657ffdec3121de388d089066 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 11:47:28 +0330 Subject: [PATCH 351/775] Commit 166 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 5c153293b..ff5764006 100644 --- a/render/march3.go +++ b/render/march3.go @@ -691,6 +691,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 4, 10, 1, 2, 7, 6, 11}, // 0b10100101 case 165 {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5}, + // 0b10100110 case 166 {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2}, {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6}, {7, 2, 3, 7, 6, 2, 5, 4, 9}, From 9277e80db3c4300b35cc2c19bae8a3a23e2b03d0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 12:04:58 +0330 Subject: [PATCH 352/775] Case 167 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ff5764006..3be7c9a90 100644 --- a/render/march3.go +++ b/render/march3.go @@ -693,6 +693,7 @@ var mcTriangleTable = [256][]int{ {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5}, // 0b10100110 case 166 {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2}, + // 0b10100111 case 167 {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6}, {7, 2, 3, 7, 6, 2, 5, 4, 9}, {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7}, From 64cef6363e028b5b2a12b2d76c3d65886ceb8fbd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 12:15:34 +0330 Subject: [PATCH 353/775] Case 168 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 3be7c9a90..5c4165b58 100644 --- a/render/march3.go +++ b/render/march3.go @@ -695,6 +695,7 @@ var mcTriangleTable = [256][]int{ {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2}, // 0b10100111 case 167 {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6}, + // 0b10101000 case 168 {7, 2, 3, 7, 6, 2, 5, 4, 9}, {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7}, {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0}, From aeb24d1f72e369e8f6b58ff1a34397e61e44963b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 12:25:03 +0330 Subject: [PATCH 354/775] Case 169 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 5c4165b58..41a46ea4e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -697,6 +697,7 @@ var mcTriangleTable = [256][]int{ {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6}, // 0b10101000 case 168 {7, 2, 3, 7, 6, 2, 5, 4, 9}, + // 0b10101001 case 169 {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7}, {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0}, {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8}, From 58f9b8f2be1ecb797a81b70ccb588ec12bd7bdbc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 12:40:05 +0330 Subject: [PATCH 355/775] Case 170 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 41a46ea4e..a50240c1b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -699,6 +699,7 @@ var mcTriangleTable = [256][]int{ {7, 2, 3, 7, 6, 2, 5, 4, 9}, // 0b10101001 case 169 {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7}, + // 0b10101010 case 170 {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0}, {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8}, {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7}, From 234621e795fcd4545ef65cec29bf0c44a7004799 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 12:48:00 +0330 Subject: [PATCH 356/775] Case 171 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a50240c1b..b4a5a00b1 100644 --- a/render/march3.go +++ b/render/march3.go @@ -701,6 +701,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7}, // 0b10101010 case 170 {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0}, + // 0b10101011 case 171 {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8}, {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7}, {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4}, From b9b71dfb441600a89ee7cf2cb358c9058119dea9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 13:00:55 +0330 Subject: [PATCH 357/775] Case 172 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b4a5a00b1..fbf894d8c 100644 --- a/render/march3.go +++ b/render/march3.go @@ -703,6 +703,7 @@ var mcTriangleTable = [256][]int{ {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0}, // 0b10101011 case 171 {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8}, + // 0b10101100 case 172 {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7}, {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4}, {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10}, From b58ba8620af39d2005acc3fab27bf051fbdcbeaf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 13:21:44 +0330 Subject: [PATCH 358/775] Case 173 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fbf894d8c..d2881f013 100644 --- a/render/march3.go +++ b/render/march3.go @@ -705,6 +705,7 @@ var mcTriangleTable = [256][]int{ {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8}, // 0b10101100 case 172 {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7}, + // 0b10101101 case 173 {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4}, {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10}, {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10}, From a63cf46c7a1594c03158028adb94a5c6fb091a0b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 13:35:58 +0330 Subject: [PATCH 359/775] Case 174 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d2881f013..8f1c70bc8 100644 --- a/render/march3.go +++ b/render/march3.go @@ -707,6 +707,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7}, // 0b10101101 case 173 {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4}, + // 0b10101110 case 174 {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10}, {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10}, {6, 9, 5, 6, 11, 9, 11, 8, 9}, From b6c4dcb3cbc4327e9afa38f2bfb84033b5f628bc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 13:50:34 +0330 Subject: [PATCH 360/775] Case 175 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8f1c70bc8..914fde361 100644 --- a/render/march3.go +++ b/render/march3.go @@ -709,6 +709,7 @@ var mcTriangleTable = [256][]int{ {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4}, // 0b10101110 case 174 {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10}, + // 0b10101111 case 175 {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10}, {6, 9, 5, 6, 11, 9, 11, 8, 9}, {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5}, From ca1f2c62db8fe93e961ae3670f2c51ad9e02e562 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 14:02:43 +0330 Subject: [PATCH 361/775] Case 176 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 914fde361..cf7e8d7b7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -711,6 +711,7 @@ var mcTriangleTable = [256][]int{ {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10}, // 0b10101111 case 175 {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10}, + // 0b10110000 case 176 {6, 9, 5, 6, 11, 9, 11, 8, 9}, {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5}, {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11}, From 71f68a8c5af74398cf4d4eccfbef62fbf431fc59 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 14:13:31 +0330 Subject: [PATCH 362/775] Case 177 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index cf7e8d7b7..e0cf6d5cc 100644 --- a/render/march3.go +++ b/render/march3.go @@ -713,6 +713,7 @@ var mcTriangleTable = [256][]int{ {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10}, // 0b10110000 case 176 {6, 9, 5, 6, 11, 9, 11, 8, 9}, + // 0b10110001 case 177 {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5}, {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11}, {6, 11, 3, 6, 3, 5, 5, 3, 1}, From 2fcb99138dd151f43a5fe31eb94b016e913354d2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 14:26:24 +0330 Subject: [PATCH 363/775] Case 178 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e0cf6d5cc..62e4e10fd 100644 --- a/render/march3.go +++ b/render/march3.go @@ -715,6 +715,7 @@ var mcTriangleTable = [256][]int{ {6, 9, 5, 6, 11, 9, 11, 8, 9}, // 0b10110001 case 177 {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5}, + // 0b10110010 case 178 {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11}, {6, 11, 3, 6, 3, 5, 5, 3, 1}, {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6}, From 5d966cdfba08e201e389ac56ddf44cf8af2e3673 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 14:39:26 +0330 Subject: [PATCH 364/775] Case 179 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 62e4e10fd..ce69a3844 100644 --- a/render/march3.go +++ b/render/march3.go @@ -717,6 +717,7 @@ var mcTriangleTable = [256][]int{ {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5}, // 0b10110010 case 178 {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11}, + // 0b10110011 case 179 {6, 11, 3, 6, 3, 5, 5, 3, 1}, {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6}, {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10}, From 5fdf1d1c7bb96d51cf86ce1a1a3d3fa26a3fc8e7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 14:52:03 +0330 Subject: [PATCH 365/775] Case 180 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ce69a3844..7eae75076 100644 --- a/render/march3.go +++ b/render/march3.go @@ -719,6 +719,7 @@ var mcTriangleTable = [256][]int{ {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11}, // 0b10110011 case 179 {6, 11, 3, 6, 3, 5, 5, 3, 1}, + // 0b10110100 case 180 {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6}, {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10}, {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5}, From 5c682b748942ddb577291f0e3b0e7ca4e9759ec9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 15:01:38 +0330 Subject: [PATCH 366/775] Case 181 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7eae75076..5346592bb 100644 --- a/render/march3.go +++ b/render/march3.go @@ -721,6 +721,7 @@ var mcTriangleTable = [256][]int{ {6, 11, 3, 6, 3, 5, 5, 3, 1}, // 0b10110100 case 180 {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6}, + // 0b10110101 case 181 {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10}, {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5}, {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3}, From e18d69c2f72b422d4236f88e6a95921af1385a86 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 15:07:28 +0330 Subject: [PATCH 367/775] Case 182 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 5346592bb..73f9e259f 100644 --- a/render/march3.go +++ b/render/march3.go @@ -723,6 +723,7 @@ var mcTriangleTable = [256][]int{ {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6}, // 0b10110101 case 181 {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10}, + // 0b10110110 case 182 {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5}, {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3}, {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2}, From 1643e2809170338f33befc6a62434fca0c674649 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 18:10:37 +0330 Subject: [PATCH 368/775] Case 183 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 73f9e259f..8295004d7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -725,6 +725,7 @@ var mcTriangleTable = [256][]int{ {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10}, // 0b10110110 case 182 {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5}, + // 0b10110111 case 183 {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3}, {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2}, {9, 5, 6, 9, 6, 0, 0, 6, 2}, From f71ae5fe162973085bcfb41eac2bb97fdbcac6bf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 18:20:50 +0330 Subject: [PATCH 369/775] Case 184 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8295004d7..0d1084952 100644 --- a/render/march3.go +++ b/render/march3.go @@ -727,6 +727,7 @@ var mcTriangleTable = [256][]int{ {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5}, // 0b10110111 case 183 {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3}, + // 0b10111000 case 184 {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2}, {9, 5, 6, 9, 6, 0, 0, 6, 2}, {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8}, From 795cc5b0e8deb15ee7c90c3a0c864a18e30827e1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 18:36:58 +0330 Subject: [PATCH 370/775] Case 185 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 0d1084952..e42da95b1 100644 --- a/render/march3.go +++ b/render/march3.go @@ -729,6 +729,7 @@ var mcTriangleTable = [256][]int{ {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3}, // 0b10111000 case 184 {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2}, + // 0b10111001 case 185 {9, 5, 6, 9, 6, 0, 0, 6, 2}, {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8}, {1, 5, 6, 2, 1, 6}, From 22e5e1e9b53e13603675b3a9a056a882da84696b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 18:47:29 +0330 Subject: [PATCH 371/775] Case 186 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e42da95b1..a69b97ecf 100644 --- a/render/march3.go +++ b/render/march3.go @@ -731,6 +731,7 @@ var mcTriangleTable = [256][]int{ {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2}, // 0b10111001 case 185 {9, 5, 6, 9, 6, 0, 0, 6, 2}, + // 0b10111010 case 186 {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8}, {1, 5, 6, 2, 1, 6}, {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6}, From ec8c8407261f28069fdf391fa91ec098230b01a6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 19:09:59 +0330 Subject: [PATCH 372/775] Case 187 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index a69b97ecf..42cde1dcd 100644 --- a/render/march3.go +++ b/render/march3.go @@ -733,6 +733,7 @@ var mcTriangleTable = [256][]int{ {9, 5, 6, 9, 6, 0, 0, 6, 2}, // 0b10111010 case 186 {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8}, + // 0b10111011 case 187 {1, 5, 6, 2, 1, 6}, {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6}, {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0}, From 9a53baf6ed8cfdd34818a0863e176ddf9c05aff8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 23 May 2023 19:25:40 +0330 Subject: [PATCH 373/775] Case 188 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 42cde1dcd..ca7a84530 100644 --- a/render/march3.go +++ b/render/march3.go @@ -735,6 +735,7 @@ var mcTriangleTable = [256][]int{ {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8}, // 0b10111011 case 187 {1, 5, 6, 2, 1, 6}, + // 0b10111100 case 188 {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6}, {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0}, {0, 3, 8, 5, 6, 10}, From 564ee25a21dc70df4cb48d406b700054f9f66dd0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 09:17:09 +0330 Subject: [PATCH 374/775] Case 189 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ca7a84530..ce794f146 100644 --- a/render/march3.go +++ b/render/march3.go @@ -737,6 +737,7 @@ var mcTriangleTable = [256][]int{ {1, 5, 6, 2, 1, 6}, // 0b10111100 case 188 {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6}, + // 0b10111101 case 189 {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0}, {0, 3, 8, 5, 6, 10}, {10, 5, 6}, From e18d222b841874f81791a3c7102bf443c9fe13d8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 10:01:29 +0330 Subject: [PATCH 375/775] Case 190 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ce794f146..1cbc986f2 100644 --- a/render/march3.go +++ b/render/march3.go @@ -739,6 +739,7 @@ var mcTriangleTable = [256][]int{ {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6}, // 0b10111101 case 189 {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0}, + // 0b10111110 case 190 {0, 3, 8, 5, 6, 10}, {10, 5, 6}, {11, 5, 10, 7, 5, 11}, From 93badccf8c803fcc9c6ab313e83b2a429bfb589e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 10:20:40 +0330 Subject: [PATCH 376/775] Case 191 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 1cbc986f2..7aad41b67 100644 --- a/render/march3.go +++ b/render/march3.go @@ -741,6 +741,7 @@ var mcTriangleTable = [256][]int{ {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0}, // 0b10111110 case 190 {0, 3, 8, 5, 6, 10}, + // 0b10111111 case 191 {10, 5, 6}, {11, 5, 10, 7, 5, 11}, {11, 5, 10, 11, 7, 5, 8, 3, 0}, From e5f57902e95fc7f022b2c37f773acec8a801891e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 10:35:29 +0330 Subject: [PATCH 377/775] Case 192 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7aad41b67..7e6f841db 100644 --- a/render/march3.go +++ b/render/march3.go @@ -743,6 +743,7 @@ var mcTriangleTable = [256][]int{ {0, 3, 8, 5, 6, 10}, // 0b10111111 case 191 {10, 5, 6}, + // 0b11000000 case 192 {11, 5, 10, 7, 5, 11}, {11, 5, 10, 11, 7, 5, 8, 3, 0}, {5, 11, 7, 5, 10, 11, 1, 9, 0}, From 666557c37a9e401d89b7cf9b7271df9fa436c94c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 11:02:00 +0330 Subject: [PATCH 378/775] Case 193 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7e6f841db..ddb632612 100644 --- a/render/march3.go +++ b/render/march3.go @@ -745,6 +745,7 @@ var mcTriangleTable = [256][]int{ {10, 5, 6}, // 0b11000000 case 192 {11, 5, 10, 7, 5, 11}, + // 0b11000001 case 193 {11, 5, 10, 11, 7, 5, 8, 3, 0}, {5, 11, 7, 5, 10, 11, 1, 9, 0}, {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1}, From 5d1754550b33cfe4e4d512bfd22424b235572749 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 11:11:53 +0330 Subject: [PATCH 379/775] Case 194 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ddb632612..30ac28396 100644 --- a/render/march3.go +++ b/render/march3.go @@ -747,6 +747,7 @@ var mcTriangleTable = [256][]int{ {11, 5, 10, 7, 5, 11}, // 0b11000001 case 193 {11, 5, 10, 11, 7, 5, 8, 3, 0}, + // 0b11000010 case 194 {5, 11, 7, 5, 10, 11, 1, 9, 0}, {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1}, {11, 1, 2, 11, 7, 1, 7, 5, 1}, From ef001ba75642f61ac6af194f6118cfe6c42d30d1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 11:21:24 +0330 Subject: [PATCH 380/775] Case 195 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 30ac28396..8da75695c 100644 --- a/render/march3.go +++ b/render/march3.go @@ -749,6 +749,7 @@ var mcTriangleTable = [256][]int{ {11, 5, 10, 11, 7, 5, 8, 3, 0}, // 0b11000010 case 194 {5, 11, 7, 5, 10, 11, 1, 9, 0}, + // 0b11000011 case 195 {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1}, {11, 1, 2, 11, 7, 1, 7, 5, 1}, {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11}, From 892ac567f0386a9398dc22b28a3c2b13dc7018ab Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 11:37:24 +0330 Subject: [PATCH 381/775] Case 196 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8da75695c..463cae2a2 100644 --- a/render/march3.go +++ b/render/march3.go @@ -751,6 +751,7 @@ var mcTriangleTable = [256][]int{ {5, 11, 7, 5, 10, 11, 1, 9, 0}, // 0b11000011 case 195 {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1}, + // 0b11000100 case 196 {11, 1, 2, 11, 7, 1, 7, 5, 1}, {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11}, {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7}, From c2050dd1415978a3da0aaf429273e0172898feac Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 11:46:41 +0330 Subject: [PATCH 382/775] Case 197 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 463cae2a2..6d2cf8a13 100644 --- a/render/march3.go +++ b/render/march3.go @@ -753,6 +753,7 @@ var mcTriangleTable = [256][]int{ {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1}, // 0b11000100 case 196 {11, 1, 2, 11, 7, 1, 7, 5, 1}, + // 0b11000101 case 197 {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11}, {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7}, {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2}, From c7d291793e7ed574524fe2a7fc5a9a19e510c774 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 11:56:49 +0330 Subject: [PATCH 383/775] Case 198 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 6d2cf8a13..675c7d72d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -755,6 +755,7 @@ var mcTriangleTable = [256][]int{ {11, 1, 2, 11, 7, 1, 7, 5, 1}, // 0b11000101 case 197 {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11}, + // 0b11000110 case 198 {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7}, {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2}, {2, 5, 10, 2, 3, 5, 3, 7, 5}, From 18a888c4ae4e4609470d0ae6f729eb49aecdb055 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 12:12:51 +0330 Subject: [PATCH 384/775] Case 199 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 675c7d72d..56a4a2d23 100644 --- a/render/march3.go +++ b/render/march3.go @@ -757,6 +757,7 @@ var mcTriangleTable = [256][]int{ {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11}, // 0b11000110 case 198 {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7}, + // 0b11000111 case 199 {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2}, {2, 5, 10, 2, 3, 5, 3, 7, 5}, {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5}, From d80f176fe325a1ea7a4d9f5b612f9bcca6ae33c7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 12:27:29 +0330 Subject: [PATCH 385/775] Case 200 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 56a4a2d23..417e1a72d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -759,6 +759,7 @@ var mcTriangleTable = [256][]int{ {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7}, // 0b11000111 case 199 {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2}, + // 0b11001000 case 200 {2, 5, 10, 2, 3, 5, 3, 7, 5}, {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5}, {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2}, From b7c6071353fa4adf477b145321c2a390f1dbf229 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 12:43:20 +0330 Subject: [PATCH 386/775] Case 201 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 417e1a72d..24ced5f83 100644 --- a/render/march3.go +++ b/render/march3.go @@ -761,6 +761,7 @@ var mcTriangleTable = [256][]int{ {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2}, // 0b11001000 case 200 {2, 5, 10, 2, 3, 5, 3, 7, 5}, + // 0b11001001 case 201 {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5}, {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2}, {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2}, From 1b46969a4c79503c88ed0684de5d2228ead4cbd8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 12:56:44 +0330 Subject: [PATCH 387/775] Case 202 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 24ced5f83..69139c420 100644 --- a/render/march3.go +++ b/render/march3.go @@ -763,6 +763,7 @@ var mcTriangleTable = [256][]int{ {2, 5, 10, 2, 3, 5, 3, 7, 5}, // 0b11001001 case 201 {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5}, + // 0b11001010 case 202 {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2}, {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2}, {1, 3, 5, 3, 7, 5}, From 80b9415dd479c45eff320b0784480486f9f47051 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 13:22:58 +0330 Subject: [PATCH 388/775] Case 203 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 69139c420..de75c7f92 100644 --- a/render/march3.go +++ b/render/march3.go @@ -765,6 +765,7 @@ var mcTriangleTable = [256][]int{ {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5}, // 0b11001010 case 202 {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2}, + // 0b11001011 case 203 {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2}, {1, 3, 5, 3, 7, 5}, {0, 8, 7, 0, 7, 1, 1, 7, 5}, From dcbd4e934bd2fef7a60bbea33a620e8bd9bc8225 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 13:53:40 +0330 Subject: [PATCH 389/775] Case 204 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index de75c7f92..7a4acbd40 100644 --- a/render/march3.go +++ b/render/march3.go @@ -767,6 +767,7 @@ var mcTriangleTable = [256][]int{ {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2}, // 0b11001011 case 203 {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2}, + // 0b11001100 case 204 {1, 3, 5, 3, 7, 5}, {0, 8, 7, 0, 7, 1, 1, 7, 5}, {9, 0, 3, 9, 3, 5, 5, 3, 7}, From 4d22719bb2e486c057b9458c20f9a4f2e5b80ea8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 14:05:57 +0330 Subject: [PATCH 390/775] Case 205 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7a4acbd40..1a7d1e798 100644 --- a/render/march3.go +++ b/render/march3.go @@ -769,6 +769,7 @@ var mcTriangleTable = [256][]int{ {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2}, // 0b11001100 case 204 {1, 3, 5, 3, 7, 5}, + // 0b11001101 case 205 {0, 8, 7, 0, 7, 1, 1, 7, 5}, {9, 0, 3, 9, 3, 5, 5, 3, 7}, {9, 8, 7, 5, 9, 7}, From cd79ea9d830a5a79e0a90d1762fbcb7d585f377b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 14:22:50 +0330 Subject: [PATCH 391/775] Case 206 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 1a7d1e798..9e86811b2 100644 --- a/render/march3.go +++ b/render/march3.go @@ -771,6 +771,7 @@ var mcTriangleTable = [256][]int{ {1, 3, 5, 3, 7, 5}, // 0b11001101 case 205 {0, 8, 7, 0, 7, 1, 1, 7, 5}, + // 0b11001110 case 206 {9, 0, 3, 9, 3, 5, 5, 3, 7}, {9, 8, 7, 5, 9, 7}, {5, 8, 4, 5, 10, 8, 10, 11, 8}, From d9ebc4191366683bdfe54ec2646a8f1d92fdacec Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 14:44:23 +0330 Subject: [PATCH 392/775] Case 207 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9e86811b2..084666814 100644 --- a/render/march3.go +++ b/render/march3.go @@ -773,6 +773,7 @@ var mcTriangleTable = [256][]int{ {0, 8, 7, 0, 7, 1, 1, 7, 5}, // 0b11001110 case 206 {9, 0, 3, 9, 3, 5, 5, 3, 7}, + // 0b11001111 case 207 {9, 8, 7, 5, 9, 7}, {5, 8, 4, 5, 10, 8, 10, 11, 8}, {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0}, From a4567e1d616e7da31606fcb4914a37710c9ad06e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 14:53:17 +0330 Subject: [PATCH 393/775] Case 208 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 084666814..40d562329 100644 --- a/render/march3.go +++ b/render/march3.go @@ -775,6 +775,7 @@ var mcTriangleTable = [256][]int{ {9, 0, 3, 9, 3, 5, 5, 3, 7}, // 0b11001111 case 207 {9, 8, 7, 5, 9, 7}, + // 0b11010000 case 208 {5, 8, 4, 5, 10, 8, 10, 11, 8}, {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0}, {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5}, From 2535c4559f0a1ce8e9665728f0fd5ef364237512 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 15:14:50 +0330 Subject: [PATCH 394/775] Case 209 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 40d562329..9d313b908 100644 --- a/render/march3.go +++ b/render/march3.go @@ -777,6 +777,7 @@ var mcTriangleTable = [256][]int{ {9, 8, 7, 5, 9, 7}, // 0b11010000 case 208 {5, 8, 4, 5, 10, 8, 10, 11, 8}, + // 0b11010001 case 209 {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0}, {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5}, {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4}, From 1d19935f429e3f9b925aa608d1957bd801f137fe Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 15:29:08 +0330 Subject: [PATCH 395/775] Case 210 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9d313b908..9f7aff2a5 100644 --- a/render/march3.go +++ b/render/march3.go @@ -779,6 +779,7 @@ var mcTriangleTable = [256][]int{ {5, 8, 4, 5, 10, 8, 10, 11, 8}, // 0b11010001 case 209 {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0}, + // 0b11010010 case 210 {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5}, {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4}, {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8}, From 13fd2c2552a1e023ff09e6236e1102fb92df19cd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 15:40:59 +0330 Subject: [PATCH 396/775] Case 211 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9f7aff2a5..bc28c6075 100644 --- a/render/march3.go +++ b/render/march3.go @@ -781,6 +781,7 @@ var mcTriangleTable = [256][]int{ {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0}, // 0b11010010 case 210 {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5}, + // 0b11010011 case 211 {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4}, {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8}, {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11}, From 305fdd18b13ae4a876ffa7471608786eb9fc7ee7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 15:53:07 +0330 Subject: [PATCH 397/775] Case 212 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index bc28c6075..d4cf4d68d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -783,6 +783,7 @@ var mcTriangleTable = [256][]int{ {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5}, // 0b11010011 case 211 {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4}, + // 0b11010100 case 212 {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8}, {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11}, {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5}, From 649e69c9f52ef0b67c6e6b9cca2c7e7f6e43539c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 16:06:12 +0330 Subject: [PATCH 398/775] Case 213 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d4cf4d68d..f632a6317 100644 --- a/render/march3.go +++ b/render/march3.go @@ -785,6 +785,7 @@ var mcTriangleTable = [256][]int{ {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4}, // 0b11010100 case 212 {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8}, + // 0b11010101 case 213 {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11}, {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5}, {9, 4, 5, 2, 11, 3}, From 2d3838915963bb7750fffd48574dbc64a0aa8363 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 16:17:55 +0330 Subject: [PATCH 399/775] Case 214 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index f632a6317..ffcc0016f 100644 --- a/render/march3.go +++ b/render/march3.go @@ -787,6 +787,7 @@ var mcTriangleTable = [256][]int{ {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8}, // 0b11010101 case 213 {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11}, + // 0b11010110 case 214 {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5}, {9, 4, 5, 2, 11, 3}, {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4}, From 613e000855424e8bf5ee62a8b59b4255a7b4bdab Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 16:30:06 +0330 Subject: [PATCH 400/775] Case 215 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ffcc0016f..ca407344d 100644 --- a/render/march3.go +++ b/render/march3.go @@ -789,6 +789,7 @@ var mcTriangleTable = [256][]int{ {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11}, // 0b11010110 case 214 {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5}, + // 0b11010111 case 215 {9, 4, 5, 2, 11, 3}, {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4}, {5, 10, 2, 5, 2, 4, 4, 2, 0}, From 74f4e62a077d144310650f74f04915d4dd9e97d9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 16:45:47 +0330 Subject: [PATCH 401/775] Case 216 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ca407344d..bb0c6cccf 100644 --- a/render/march3.go +++ b/render/march3.go @@ -791,6 +791,7 @@ var mcTriangleTable = [256][]int{ {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5}, // 0b11010111 case 215 {9, 4, 5, 2, 11, 3}, + // 0b11011000 case 216 {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4}, {5, 10, 2, 5, 2, 4, 4, 2, 0}, {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9}, From dcb0f596c6ce5bc5d974b11f1dfb6817110f1245 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 17:13:34 +0330 Subject: [PATCH 402/775] Case 217 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index bb0c6cccf..384098642 100644 --- a/render/march3.go +++ b/render/march3.go @@ -793,6 +793,7 @@ var mcTriangleTable = [256][]int{ {9, 4, 5, 2, 11, 3}, // 0b11011000 case 216 {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4}, + // 0b11011001 case 217 {5, 10, 2, 5, 2, 4, 4, 2, 0}, {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9}, {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2}, From ac3e83dbf86608534c21b9a6402205f9df9fc05f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 24 May 2023 17:22:56 +0330 Subject: [PATCH 403/775] Case 218 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 384098642..b0af55939 100644 --- a/render/march3.go +++ b/render/march3.go @@ -795,6 +795,7 @@ var mcTriangleTable = [256][]int{ {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4}, // 0b11011001 case 217 {5, 10, 2, 5, 2, 4, 4, 2, 0}, + // 0b11011010 case 218 {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9}, {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2}, {8, 4, 5, 8, 5, 3, 3, 5, 1}, From 49ba0f9540ba0a62ff54b2556a16b03078214faf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 09:55:41 +0330 Subject: [PATCH 404/775] Case 219 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b0af55939..91ea86027 100644 --- a/render/march3.go +++ b/render/march3.go @@ -797,6 +797,7 @@ var mcTriangleTable = [256][]int{ {5, 10, 2, 5, 2, 4, 4, 2, 0}, // 0b11011010 case 218 {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9}, + // 0b11011011 case 219 {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2}, {8, 4, 5, 8, 5, 3, 3, 5, 1}, {0, 4, 5, 1, 0, 5}, From 38228d34beaafb1305d08712ebbcf3b795ee185d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 10:13:42 +0330 Subject: [PATCH 405/775] Case 220 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 91ea86027..9afcca5b2 100644 --- a/render/march3.go +++ b/render/march3.go @@ -799,6 +799,7 @@ var mcTriangleTable = [256][]int{ {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9}, // 0b11011011 case 219 {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2}, + // 0b11011100 case 220 {8, 4, 5, 8, 5, 3, 3, 5, 1}, {0, 4, 5, 1, 0, 5}, {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5}, From 70c40d348a968a4c92e7fdf1f51d53e914e6a7b7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 10:27:10 +0330 Subject: [PATCH 406/775] Case 221 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9afcca5b2..c92cbc798 100644 --- a/render/march3.go +++ b/render/march3.go @@ -801,6 +801,7 @@ var mcTriangleTable = [256][]int{ {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2}, // 0b11011100 case 220 {8, 4, 5, 8, 5, 3, 3, 5, 1}, + // 0b11011101 case 221 {0, 4, 5, 1, 0, 5}, {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5}, {9, 4, 5}, From 754b5b05cdff7df697ffdc7e812a6eb4e2c7f5d1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 10:40:18 +0330 Subject: [PATCH 407/775] Case 222 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index c92cbc798..d7e7ffb8a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -803,6 +803,7 @@ var mcTriangleTable = [256][]int{ {8, 4, 5, 8, 5, 3, 3, 5, 1}, // 0b11011101 case 221 {0, 4, 5, 1, 0, 5}, + // 0b11011110 case 222 {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5}, {9, 4, 5}, {4, 11, 7, 4, 9, 11, 9, 10, 11}, From e064c456cdb9e37290218ea7936e8c38e9631821 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 10:53:52 +0330 Subject: [PATCH 408/775] Case 223 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d7e7ffb8a..71dbc864e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -805,6 +805,7 @@ var mcTriangleTable = [256][]int{ {0, 4, 5, 1, 0, 5}, // 0b11011110 case 222 {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5}, + // 0b11011111 case 223 {9, 4, 5}, {4, 11, 7, 4, 9, 11, 9, 10, 11}, {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11}, From ce158f5a4e0259121b726181e95f1bac30fea48e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 11:07:07 +0330 Subject: [PATCH 409/775] Case 224 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 71dbc864e..d9adfc3f7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -807,6 +807,7 @@ var mcTriangleTable = [256][]int{ {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5}, // 0b11011111 case 223 {9, 4, 5}, + // 0b11100000 case 224 {4, 11, 7, 4, 9, 11, 9, 10, 11}, {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11}, {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11}, From 2b1f2271f01ca13006101b84da71f5de2f4cc251 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 11:23:49 +0330 Subject: [PATCH 410/775] Case 225 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d9adfc3f7..44fda3764 100644 --- a/render/march3.go +++ b/render/march3.go @@ -809,6 +809,7 @@ var mcTriangleTable = [256][]int{ {9, 4, 5}, // 0b11100000 case 224 {4, 11, 7, 4, 9, 11, 9, 10, 11}, + // 0b11100001 case 225 {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11}, {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11}, {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4}, From cf22b467491c7cd65b6385230e03b5b7acd59866 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 12:07:02 +0330 Subject: [PATCH 411/775] Commit 226 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 44fda3764..488c98c3b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -811,6 +811,7 @@ var mcTriangleTable = [256][]int{ {4, 11, 7, 4, 9, 11, 9, 10, 11}, // 0b11100001 case 225 {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11}, + // 0b11100010 case 226 {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11}, {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4}, {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2}, From 4b26ac4359c867fe16f9084986ea8ee246267554 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 12:21:54 +0330 Subject: [PATCH 412/775] Case 227 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 488c98c3b..9ee5bef78 100644 --- a/render/march3.go +++ b/render/march3.go @@ -813,6 +813,7 @@ var mcTriangleTable = [256][]int{ {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11}, // 0b11100010 case 226 {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11}, + // 0b11100011 case 227 {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4}, {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2}, {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3}, From 7ae2929c16e7d68274653602097ba59458ba6174 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 12:35:38 +0330 Subject: [PATCH 413/775] Case 228 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9ee5bef78..e15233341 100644 --- a/render/march3.go +++ b/render/march3.go @@ -815,6 +815,7 @@ var mcTriangleTable = [256][]int{ {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11}, // 0b11100011 case 227 {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4}, + // 0b11100100 case 228 {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2}, {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3}, {11, 7, 4, 11, 4, 2, 2, 4, 0}, From a5e1859562d3d58fd6bd5a0a3c1da1dc9b751983 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 12:45:01 +0330 Subject: [PATCH 414/775] Case 229 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e15233341..7822bbc7e 100644 --- a/render/march3.go +++ b/render/march3.go @@ -817,6 +817,7 @@ var mcTriangleTable = [256][]int{ {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4}, // 0b11100100 case 228 {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2}, + // 0b11100101 case 229 {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3}, {11, 7, 4, 11, 4, 2, 2, 4, 0}, {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4}, From d786cdf6381fed07d745bb4c5c89ec751713b029 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 12:51:31 +0330 Subject: [PATCH 415/775] Case 230 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 7822bbc7e..e017e8c02 100644 --- a/render/march3.go +++ b/render/march3.go @@ -819,6 +819,7 @@ var mcTriangleTable = [256][]int{ {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2}, // 0b11100101 case 229 {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3}, + // 0b11100110 case 230 {11, 7, 4, 11, 4, 2, 2, 4, 0}, {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4}, {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9}, From f5439a29ab826f258e8f5495d51a4f2b2b865015 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 13:06:00 +0330 Subject: [PATCH 416/775] Case 231 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e017e8c02..fb75ae67f 100644 --- a/render/march3.go +++ b/render/march3.go @@ -821,6 +821,7 @@ var mcTriangleTable = [256][]int{ {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3}, // 0b11100110 case 230 {11, 7, 4, 11, 4, 2, 2, 4, 0}, + // 0b11100111 case 231 {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4}, {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9}, {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7}, From 1b729adaf860605721b0016a6364816e85ecf5a4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 13:22:08 +0330 Subject: [PATCH 417/775] Case 232 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fb75ae67f..fe165cf97 100644 --- a/render/march3.go +++ b/render/march3.go @@ -823,6 +823,7 @@ var mcTriangleTable = [256][]int{ {11, 7, 4, 11, 4, 2, 2, 4, 0}, // 0b11100111 case 231 {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4}, + // 0b11101000 case 232 {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9}, {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7}, {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10}, From 5b0021144532af0bee61cd1692571a9f927ee38c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 13:32:16 +0330 Subject: [PATCH 418/775] Case 233 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index fe165cf97..9eebb5caa 100644 --- a/render/march3.go +++ b/render/march3.go @@ -825,6 +825,7 @@ var mcTriangleTable = [256][]int{ {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4}, // 0b11101000 case 232 {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9}, + // 0b11101001 case 233 {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7}, {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10}, {1, 10, 2, 8, 7, 4}, From 92e28d9dcc4d5936770caa173febe156e8eeeb09 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 13:41:17 +0330 Subject: [PATCH 419/775] Case 234 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 9eebb5caa..d0e2a3e83 100644 --- a/render/march3.go +++ b/render/march3.go @@ -827,6 +827,7 @@ var mcTriangleTable = [256][]int{ {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9}, // 0b11101001 case 233 {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7}, + // 0b11101010 case 234 {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10}, {1, 10, 2, 8, 7, 4}, {4, 9, 1, 4, 1, 7, 7, 1, 3}, From cc6f279a9e2242085d81c7275fca732ac767c299 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 13:54:52 +0330 Subject: [PATCH 420/775] Case 235 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index d0e2a3e83..f45b5b594 100644 --- a/render/march3.go +++ b/render/march3.go @@ -829,6 +829,7 @@ var mcTriangleTable = [256][]int{ {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7}, // 0b11101010 case 234 {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10}, + // 0b11101011 case 235 {1, 10, 2, 8, 7, 4}, {4, 9, 1, 4, 1, 7, 7, 1, 3}, {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1}, From b132ddac3f2c6b5edde149a9b93e8b3c63351fdd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 14:36:04 +0330 Subject: [PATCH 421/775] Case 236 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index f45b5b594..c882faa73 100644 --- a/render/march3.go +++ b/render/march3.go @@ -831,6 +831,7 @@ var mcTriangleTable = [256][]int{ {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10}, // 0b11101011 case 235 {1, 10, 2, 8, 7, 4}, + // 0b11101100 case 236 {4, 9, 1, 4, 1, 7, 7, 1, 3}, {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1}, {4, 0, 3, 7, 4, 3}, From 93876b5d09cdd03149b3f38962c3f941e17c5782 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 14:55:07 +0330 Subject: [PATCH 422/775] Case 237 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index c882faa73..e484476ec 100644 --- a/render/march3.go +++ b/render/march3.go @@ -833,6 +833,7 @@ var mcTriangleTable = [256][]int{ {1, 10, 2, 8, 7, 4}, // 0b11101100 case 236 {4, 9, 1, 4, 1, 7, 7, 1, 3}, + // 0b11101101 case 237 {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1}, {4, 0, 3, 7, 4, 3}, {4, 8, 7}, From f22bcd018ccff25a8ce20d43a692f41282b408a4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 15:36:24 +0330 Subject: [PATCH 423/775] Case 238 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index e484476ec..58020886b 100644 --- a/render/march3.go +++ b/render/march3.go @@ -835,6 +835,7 @@ var mcTriangleTable = [256][]int{ {4, 9, 1, 4, 1, 7, 7, 1, 3}, // 0b11101101 case 237 {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1}, + // 0b11101110 case 238 {4, 0, 3, 7, 4, 3}, {4, 8, 7}, {9, 10, 8, 10, 11, 8}, From b8b3250b414a0ddabe691252f0dabd77f634fa47 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 16:01:40 +0330 Subject: [PATCH 424/775] Case 239 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 58020886b..f67cbfa01 100644 --- a/render/march3.go +++ b/render/march3.go @@ -837,6 +837,7 @@ var mcTriangleTable = [256][]int{ {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1}, // 0b11101110 case 238 {4, 0, 3, 7, 4, 3}, + // 0b11101111 case 239 {4, 8, 7}, {9, 10, 8, 10, 11, 8}, {3, 0, 9, 3, 9, 11, 11, 9, 10}, From 5a9bc6e5f408a662c9a41d7d7fbd8ad1143b9fd3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 16:25:46 +0330 Subject: [PATCH 425/775] Case 240 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index f67cbfa01..09dcc0af2 100644 --- a/render/march3.go +++ b/render/march3.go @@ -839,6 +839,7 @@ var mcTriangleTable = [256][]int{ {4, 0, 3, 7, 4, 3}, // 0b11101111 case 239 {4, 8, 7}, + // 0b11110000 case 240 {9, 10, 8, 10, 11, 8}, {3, 0, 9, 3, 9, 11, 11, 9, 10}, {0, 1, 10, 0, 10, 8, 8, 10, 11}, From d85f5895e48d53c81174e0514ad0b65a41515d63 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 16:42:16 +0330 Subject: [PATCH 426/775] Case 241 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 09dcc0af2..4863b60d3 100644 --- a/render/march3.go +++ b/render/march3.go @@ -841,6 +841,7 @@ var mcTriangleTable = [256][]int{ {4, 8, 7}, // 0b11110000 case 240 {9, 10, 8, 10, 11, 8}, + // 0b11110001 case 241 {3, 0, 9, 3, 9, 11, 11, 9, 10}, {0, 1, 10, 0, 10, 8, 8, 10, 11}, {3, 1, 10, 11, 3, 10}, From b5ed056c2a043c139d14846031a4c68f1220783b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 17:35:21 +0330 Subject: [PATCH 427/775] Case 242 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 4863b60d3..ab33f67fe 100644 --- a/render/march3.go +++ b/render/march3.go @@ -843,6 +843,7 @@ var mcTriangleTable = [256][]int{ {9, 10, 8, 10, 11, 8}, // 0b11110001 case 241 {3, 0, 9, 3, 9, 11, 11, 9, 10}, + // 0b11110010 case 242 {0, 1, 10, 0, 10, 8, 8, 10, 11}, {3, 1, 10, 11, 3, 10}, {1, 2, 11, 1, 11, 9, 9, 11, 8}, From e9ef1a88270694bdc496293869adcd19bcf65ea6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 17:46:08 +0330 Subject: [PATCH 428/775] Case 243 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ab33f67fe..da4305454 100644 --- a/render/march3.go +++ b/render/march3.go @@ -845,6 +845,7 @@ var mcTriangleTable = [256][]int{ {3, 0, 9, 3, 9, 11, 11, 9, 10}, // 0b11110010 case 242 {0, 1, 10, 0, 10, 8, 8, 10, 11}, + // 0b11110011 case 243 {3, 1, 10, 11, 3, 10}, {1, 2, 11, 1, 11, 9, 9, 11, 8}, {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9}, From 38ec83b4c127ecb954f3cd242208b2a05e0f446d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 18:01:59 +0330 Subject: [PATCH 429/775] Case 244 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index da4305454..658654c9c 100644 --- a/render/march3.go +++ b/render/march3.go @@ -847,6 +847,7 @@ var mcTriangleTable = [256][]int{ {0, 1, 10, 0, 10, 8, 8, 10, 11}, // 0b11110011 case 243 {3, 1, 10, 11, 3, 10}, + // 0b11110100 case 244 {1, 2, 11, 1, 11, 9, 9, 11, 8}, {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9}, {0, 2, 11, 8, 0, 11}, From 9e6db2f30bd7f479ef8a9aa571ce50edeed99cd8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 18:11:03 +0330 Subject: [PATCH 430/775] Case 245 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 658654c9c..42675d5f7 100644 --- a/render/march3.go +++ b/render/march3.go @@ -849,6 +849,7 @@ var mcTriangleTable = [256][]int{ {3, 1, 10, 11, 3, 10}, // 0b11110100 case 244 {1, 2, 11, 1, 11, 9, 9, 11, 8}, + // 0b11110101 case 245 {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9}, {0, 2, 11, 8, 0, 11}, {3, 2, 11}, From 2bf48995f80bc39467434c978850bf835ba64fa6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 18:23:27 +0330 Subject: [PATCH 431/775] Case 246 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 42675d5f7..81ec4c9a4 100644 --- a/render/march3.go +++ b/render/march3.go @@ -851,6 +851,7 @@ var mcTriangleTable = [256][]int{ {1, 2, 11, 1, 11, 9, 9, 11, 8}, // 0b11110101 case 245 {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9}, + // 0b11110110 case 246 {0, 2, 11, 8, 0, 11}, {3, 2, 11}, {2, 3, 8, 2, 8, 10, 10, 8, 9}, From 3c8fd98e267fa7869cdef5af98ae271ce089db31 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 18:31:40 +0330 Subject: [PATCH 432/775] Case 247 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 81ec4c9a4..716828185 100644 --- a/render/march3.go +++ b/render/march3.go @@ -853,6 +853,7 @@ var mcTriangleTable = [256][]int{ {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9}, // 0b11110110 case 246 {0, 2, 11, 8, 0, 11}, + // 0b11110111 case 247 {3, 2, 11}, {2, 3, 8, 2, 8, 10, 10, 8, 9}, {9, 10, 2, 0, 9, 2}, From 12957b2bfe867a36d29d713d4518e14ed901f257 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 25 May 2023 18:41:22 +0330 Subject: [PATCH 433/775] Case 248 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 716828185..ae5e25655 100644 --- a/render/march3.go +++ b/render/march3.go @@ -855,6 +855,7 @@ var mcTriangleTable = [256][]int{ {0, 2, 11, 8, 0, 11}, // 0b11110111 case 247 {3, 2, 11}, + // 0b11111000 case 248 {2, 3, 8, 2, 8, 10, 10, 8, 9}, {9, 10, 2, 0, 9, 2}, {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8}, From ebd819acb7456ec8eebfd14b137e4cf424783ddb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 27 May 2023 09:36:47 +0330 Subject: [PATCH 434/775] Case 249 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index ae5e25655..b7c36f297 100644 --- a/render/march3.go +++ b/render/march3.go @@ -857,6 +857,7 @@ var mcTriangleTable = [256][]int{ {3, 2, 11}, // 0b11111000 case 248 {2, 3, 8, 2, 8, 10, 10, 8, 9}, + // 0b11111001 case 249 {9, 10, 2, 0, 9, 2}, {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8}, {1, 10, 2}, From bdea4243d54909b33706200f2c17764a198b99bc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 27 May 2023 09:48:14 +0330 Subject: [PATCH 435/775] Case 250 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index b7c36f297..8c064c73f 100644 --- a/render/march3.go +++ b/render/march3.go @@ -859,6 +859,7 @@ var mcTriangleTable = [256][]int{ {2, 3, 8, 2, 8, 10, 10, 8, 9}, // 0b11111001 case 249 {9, 10, 2, 0, 9, 2}, + // 0b11111010 case 250 {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8}, {1, 10, 2}, {1, 3, 8, 9, 1, 8}, From d8dea9b052e29f37e6d7830eb5a8fea286632d7e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 27 May 2023 09:56:44 +0330 Subject: [PATCH 436/775] Case 251 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 8c064c73f..5494dce75 100644 --- a/render/march3.go +++ b/render/march3.go @@ -861,6 +861,7 @@ var mcTriangleTable = [256][]int{ {9, 10, 2, 0, 9, 2}, // 0b11111010 case 250 {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8}, + // 0b11111011 case 251 {1, 10, 2}, {1, 3, 8, 9, 1, 8}, {0, 9, 1}, From d5b87ab4bcda8fb4ede5fdb46f28afcbf17ba909 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 27 May 2023 10:04:24 +0330 Subject: [PATCH 437/775] Case 252 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 5494dce75..33c140498 100644 --- a/render/march3.go +++ b/render/march3.go @@ -863,6 +863,7 @@ var mcTriangleTable = [256][]int{ {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8}, // 0b11111011 case 251 {1, 10, 2}, + // 0b11111100 case 252 {1, 3, 8, 9, 1, 8}, {0, 9, 1}, {0, 3, 8}, From 3974a99375d0d2c6879387d230d8a6776c04f286 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 27 May 2023 10:14:14 +0330 Subject: [PATCH 438/775] Case 253 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 33c140498..2e9096459 100644 --- a/render/march3.go +++ b/render/march3.go @@ -865,6 +865,7 @@ var mcTriangleTable = [256][]int{ {1, 10, 2}, // 0b11111100 case 252 {1, 3, 8, 9, 1, 8}, + // 0b11111101 case 253 {0, 9, 1}, {0, 3, 8}, {}, From 7cd67c6ac6b300e890ccfaa6a1e54f45617ce8ac Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 27 May 2023 11:03:30 +0330 Subject: [PATCH 439/775] Case 254 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 2e9096459..4cbceb73a 100644 --- a/render/march3.go +++ b/render/march3.go @@ -867,6 +867,7 @@ var mcTriangleTable = [256][]int{ {1, 3, 8, 9, 1, 8}, // 0b11111101 case 253 {0, 9, 1}, + // 0b11111110 case 254 {0, 3, 8}, {}, } From e11304b009c63c946e902cf72a295e0bac291601 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 27 May 2023 11:14:19 +0330 Subject: [PATCH 440/775] Case 255 --- render/march3.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/march3.go b/render/march3.go index 4cbceb73a..e48e2fe24 100644 --- a/render/march3.go +++ b/render/march3.go @@ -869,6 +869,7 @@ var mcTriangleTable = [256][]int{ {0, 9, 1}, // 0b11111110 case 254 {0, 3, 8}, + // 0b11111111 case 255 {}, } From 1edae9c65b42332fcf81ef8e9e2a1f361e516656 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 27 May 2023 13:22:27 +0330 Subject: [PATCH 441/775] Bring over tetrahedron table from: https://github.com/Megidd/tetrahedron-table --- examples/finite_elements/main.go | 3 - render/march3fetet4.go | 2534 +++++++++++++++++++++++++++++- 2 files changed, 2524 insertions(+), 13 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index ed417c3b3..5f2e6367c 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -10,7 +10,6 @@ Output `inp` file is consumable by ABAQUS or CalculiX. package main import ( - "fmt" "log" "os" @@ -34,8 +33,6 @@ func tet4(s sdf.SDF3, resolution int, pth string) error { return err } - fmt.Println("Tet4 FE is not implemented, there is TODO in function mcToTet4") - return nil } diff --git a/render/march3fetet4.go b/render/march3fetet4.go index d9cad9f2e..f3e55fec6 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -71,24 +71,2538 @@ func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { //----------------------------------------------------------------------------- func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { - result := mcToTriangles(p, v, x) + // which of the 0..255 patterns do we have? + index := 0 + for i := 0; i < 8; i++ { + if v[i] < x { + index |= 1 << uint(i) + } + } - // TODO: Create tetrahedra by composing proper tables. + // work out the interpolated points on the edges + var points [12]v3.Vec + for i := 0; i < 12; i++ { + bit := 1 << uint(i) + if mcEdgeTable[index]&bit != 0 { + a := mcPairTable[i][0] + b := mcPairTable[i][1] + points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) + } + } - resultTet4 := make([]*Tet4, 0, len(result)) - for _, res := range result { + // Create the tetrahedra. + table := mcTetrahedronTable[index] + count := len(table) / 4 + result := make([]*Tet4, 0, count) + for i := 0; i < count; i++ { t := Tet4{ V: [4]v3.Vec{}, Layer: layerZ, } - t.V[3] = v3.Vec{X: 0, Y: 0, Z: 0} - t.V[2] = res.V[2] - t.V[1] = res.V[1] - t.V[0] = res.V[0] - resultTet4 = append(resultTet4, &t) + t.V[0] = point(points, p, table[i*4+0]) + t.V[1] = point(points, p, table[i*4+1]) + t.V[2] = point(points, p, table[i*4+2]) + t.V[3] = point(points, p, table[i*4+3]) + result = append(result, &t) } - return resultTet4 + return result +} + +//----------------------------------------------------------------------------- + +// Specify the point to create the tetrahedra. +// Point can be on edges or corners. +// Index from 0 to 11 means an edge. +// Index from 12 to 19 means a corner. +// Corners were originally indexed from 0 to 7 but they are shifted by 12. +// So, corners are from 0+12 to 7+12 i.e. from 12 to 19. +func point(edges [12]v3.Vec, corners [8]v3.Vec, index int) v3.Vec { + if 0 <= index && index < 12 { + return edges[index] + } else if index < 20 { + return corners[index-12] + } else { + // Should never reach here. + return v3.Vec{} + } +} + +//----------------------------------------------------------------------------- + +// Specify the edges & corners used to create the tetrahedra. +// Keep the index from 0 to 11 for edges, +// but shift the index for corners. +// Corners were originally indexed from 0 to 7. +// So, corners would be indexed from 0+12 to 7+12 i.e. from 12 to 19. +// Manually created by: +// https://github.com/Megidd/tetrahedron-table +var mcTetrahedronTable = [256][]int{ + // 0b00000000 case 0: no cube corner has zero/negative value. + {}, + // 0b00000001 case 1: first cube corner has zero/negative value. + {12, 0, 3, 8}, + // 0b00000010 case 2 + {13, 1, 0, 9}, + // 0b00000011 case 3 + { + 12, 13, 3, 8, + 13, 1, 3, 8, + 13, 1, 8, 9, + }, + // 0b00000100 case 4 + {14, 2, 1, 10}, + // 0b00000101 case 5 + { + 12, 0, 3, 8, + 14, 2, 1, 10, + }, + // 0b00000110 case 6 + { + 13, 14, 0, 9, + 14, 2, 0, 9, + 14, 2, 9, 10, + }, + // 0b00000111 case 7 + { + 12, 13, 3, 8, + 13, 2, 3, 8, + 13, 14, 2, 8, + 14, 2, 8, 10, + 13, 14, 8, 10, + 13, 10, 8, 9, + }, + // 0b00001000 case 8 + { + 15, 3, 2, 11, + }, + // 0b00001001 case 9 + { + 12, 0, 2, 11, + 12, 2, 15, 11, + 12, 0, 11, 8, + }, + // 0b00001010 case 10 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + }, + // 0b00001011 case 11 + { + 15, 12, 2, 11, + 12, 1, 2, 11, + 12, 13, 1, 11, + 13, 1, 11, 9, + 12, 13, 11, 9, + 11, 12, 9, 8, + }, + // 0b00001100 case 12 + { + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00001101 case 13 + { + 12, 0, 1, 8, + 12, 1, 14, 8, + 1, 14, 8, 10, + 14, 15, 12, 8, + 14, 15, 8, 10, + 10, 15, 8, 11, + }, + // 0b00001110 case 14 + { + 0, 15, 3, 11, + 0, 14, 15, 11, + 0, 14, 11, 9, + 0, 13, 14, 9, + 14, 11, 9, 10, + }, + // 0b00001111 case 15 + { + 12, 13, 14, 10, + 12, 13, 10, 9, + 12, 9, 10, 8, + 12, 14, 15, 8, + 14, 15, 8, 10, + 15, 8, 10, 11, + }, + // 0b00010000 case 16 + {8, 4, 7, 16}, + // 0b00010001 case 17 + { + 12, 0, 3, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b00010010 case 18 + { + 8, 4, 7, 16, + 13, 1, 0, 9, + }, + // 0b00010011 case 19 + { + 3, 12, 1, 7, + 12, 13, 1, 7, + 12, 13, 7, 16, + 13, 1, 7, 9, + 13, 7, 16, 9, + 16, 9, 7, 4, + }, + // 0b00010100 case 20 + { + 8, 4, 7, 16, + 1, 14, 2, 10, + }, + // 0b00010101 case 21 + { + 1, 14, 2, 10, + 3, 12, 0, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b00010110 case 22 + { + 8, 4, 7, 16, + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 10, + }, + // 0b00010111 case 23 + { + 3, 12, 2, 7, + 12, 13, 2, 7, + 13, 2, 7, 4, + 13, 2, 4, 9, + 12, 13, 7, 16, + 16, 13, 7, 4, + 13, 14, 2, 9, + 14, 2, 9, 10, + }, + // 0b00011000 case 24 + { + 8, 4, 7, 16, + 2, 15, 3, 11, + }, + // 0b00011001 case 25 + { + 12, 0, 2, 4, + 12, 2, 15, 4, + 2, 15, 4, 11, + 12, 4, 15, 11, + 12, 4, 11, 7, + 12, 4, 7, 16, + }, + // 0b00011010 case 26 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + 8, 4, 7, 16, + }, + // 0b00011011 case 27 + { + 12, 2, 15, 11, + 12, 1, 2, 11, + 12, 13, 1, 11, + 13, 1, 11, 9, + 12, 13, 11, 9, + 12, 9, 11, 4, + 12, 4, 11, 16, + 11, 16, 4, 7, + }, + // 0b00011100 case 28 + { + 8, 4, 7, 16, + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00011101 case 29 + { + 12, 0, 1, 4, + 3, 12, 1, 4, + 15, 3, 1, 4, + 15, 4, 1, 7, + 15, 7, 1, 11, + 15, 12, 4, 7, + 12, 4, 7, 16, + 1, 14, 15, 11, + 1, 14, 11, 10, + }, + // 0b00011110 case 30 + { + 8, 4, 7, 16, + 13, 14, 0, 9, + 14, 3, 0, 9, + 14, 15, 3, 9, + 15, 3, 9, 11, + 14, 15, 9, 11, + 14, 11, 9, 10, + }, + // 0b00011111 case 31 + { + 13, 14, 15, 11, + 13, 14, 11, 9, + 14, 11, 9, 10, + 12, 13, 15, 9, + 12, 9, 15, 11, + 12, 9, 11, 7, + 12, 9, 7, 16, + 16, 9, 7, 4, + }, + // 0b00100000 case 32 + {9, 5, 4, 17}, + // 0b00100001 case 33 + { + 12, 0, 3, 8, + 9, 5, 4, 17, + }, + // 0b00100010 case 34 + { + 0, 13, 1, 5, + 0, 13, 5, 4, + 4, 13, 5, 17, + }, + // 0b00100011 case 35 + { + 13, 1, 3, 5, + 13, 3, 12, 5, + 12, 5, 3, 4, + 12, 4, 3, 8, + 12, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00100100 case 36 + { + 1, 14, 2, 10, + 9, 5, 4, 17, + }, + // 0b00100101 case 37 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 4, 9, 5, 17, + }, + // 0b00100110 case 38 + { + 0, 14, 2, 4, + 14, 2, 4, 5, + 14, 2, 5, 10, + 0, 13, 14, 4, + 13, 14, 4, 5, + 13, 5, 4, 17, + }, + // 0b00100111 case 39 + { + 13, 14, 2, 10, + 12, 13, 2, 10, + 12, 2, 3, 10, + 12, 10, 3, 8, + 12, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 4, + 13, 5, 4, 17, + }, + // 0b00101000 case 40 + { + 9, 5, 4, 17, + 2, 15, 3, 11, + }, + // 0b00101001 case 41 + { + 9, 5, 4, 17, + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + }, + // 0b00101010 case 42 + { + 2, 15, 3, 11, + 0, 13, 1, 4, + 4, 13, 1, 5, + 4, 13, 5, 17, + }, + // 0b00101011 case 43 + { + 2, 15, 12, 11, + 11, 12, 2, 8, + 12, 1, 2, 8, + 12, 13, 1, 8, + 8, 1, 2, 5, + 13, 1, 8, 5, + 8, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00101100 case 44 + { + 9, 5, 4, 17, + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00101101 case 45 + { + 9, 5, 4, 17, + 1, 14, 0, 10, + 14, 12, 0, 10, + 12, 0, 10, 8, + 14, 15, 12, 10, + 15, 12, 10, 8, + 15, 8, 10, 11, + }, + // 0b00101110 case 46 + { + 14, 15, 3, 11, + 14, 3, 0, 11, + 0, 14, 11, 5, + 14, 11, 5, 10, + 0, 13, 14, 5, + 0, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00101111 case 47 + { + 14, 15, 12, 8, + 14, 15, 8, 10, + 15, 8, 10, 11, + 12, 13, 14, 10, + 12, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 4, + 13, 5, 4, 17, + }, + // 0b00110000 case 48 + { + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + }, + // 0b00110001 case 49 + { + 3, 12, 0, 5, + 3, 12, 5, 7, + 12, 0, 7, 16, + 0, 5, 7, 16, + 0, 5, 16, 9, + 9, 5, 16, 17, + }, + // 0b00110010 case 50 + { + 0, 13, 1, 7, + 13, 1, 7, 5, + 0, 13, 5, 17, + 0, 5, 7, 17, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b00110011 case 51 + { + 12, 1, 3, 5, + 3, 12, 5, 7, + 12, 13, 1, 5, + 12, 13, 5, 17, + 12, 17, 5, 7, + 12, 17, 7, 16, + }, + // 0b00110100 case 52 + { + 1, 14, 2, 10, + 7, 8, 5, 16, + 8, 9, 5, 16, + 16, 9, 5, 17, + }, + // 0b00110101 case 53 + { + 1, 14, 2, 10, + 3, 12, 0, 5, + 3, 12, 5, 7, + 0, 9, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 12, + 12, 17, 7, 16, + }, + // 0b00110110 case 54 + { + 13, 14, 2, 10, + 0, 13, 2, 10, + 0, 10, 2, 8, + 0, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 17, + 8, 17, 5, 7, + 8, 17, 7, 16, + }, + // 0b00110111 case 55 + { + 13, 14, 2, 10, + 13, 2, 3, 10, + 13, 10, 3, 5, + 12, 13, 3, 5, + 12, 13, 5, 17, + 3, 12, 5, 7, + 12, 17, 5, 7, + 12, 17, 7, 16, + }, + // 0b00111000 case 56 + { + 15, 3, 2, 11, + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + }, + // 0b00111001 case 57 + { + 12, 0, 2, 9, + 15, 12, 2, 9, + 2, 15, 9, 11, + 15, 12, 9, 11, + 12, 9, 11, 7, + 12, 9, 7, 16, + 9, 7, 16, 5, + 9, 5, 16, 17, + }, + // 0b00111010 case 58 + { + 15, 3, 2, 11, + 0, 13, 1, 8, + 13, 1, 8, 7, + 13, 1, 7, 5, + 13, 7, 8, 16, + 13, 7, 16, 5, + 13, 5, 16, 17, + }, + // 0b00111011 case 59 + { + 12, 13, 1, 17, + 12, 1, 17, 5, + 12, 1, 5, 7, + 12, 17, 5, 7, + 12, 17, 7, 16, + 2, 12, 1, 7, + 15, 12, 2, 7, + 15, 7, 2, 11, + }, + // 0b00111100 case 60 + { + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + 14, 3, 1, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00111101 case 61 + { + 0, 9, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 16, + 0, 16, 7, 12, + 12, 0, 7, 11, + 14, 0, 1, 10, + 12, 0, 15, 11, + 14, 15, 0, 11, + 14, 11, 0, 10, + }, + // 0b00111110 case 62 + { + 15, 3, 0, 11, + 14, 15, 0, 11, + 14, 11, 0, 10, + 14, 0, 13, 10, + 0, 13, 10, 5, + 0, 13, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b00111111 case 63 + { + 12, 14, 15, 11, + 12, 14, 11, 10, + 12, 13, 14, 10, + 11, 12, 10, 7, + 12, 13, 10, 7, + 12, 13, 7, 16, + 13, 10, 7, 5, + 13, 5, 7, 17, + 13, 7, 16, 17, + }, + // 0b01000000 case 64 + {10, 6, 5, 18}, + // 0b01000001 case 65 + { + 12, 0, 3, 8, + 10, 6, 5, 18, + }, + // 0b01000010 case 66 + { + 0, 13, 1, 9, + 10, 6, 5, 18, + }, + // 0b01000011 case 67 + { + 10, 6, 5, 18, + 3, 12, 1, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + }, + // 0b01000100 case 68 + { + 1, 14, 2, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01000101 case 69 + { + 12, 0, 3, 8, + 14, 2, 1, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01000110 case 70 + { + 0, 13, 2, 6, + 0, 13, 6, 9, + 13, 14, 2, 6, + 13, 14, 6, 9, + 9, 14, 6, 5, + 14, 6, 5, 18, + }, + // 0b01000111 case 71 + { + 3, 12, 2, 8, + 12, 13, 2, 8, + 13, 2, 8, 9, + 13, 14, 2, 9, + 9, 2, 8, 5, + 9, 14, 2, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01001000 case 72 + { + 10, 6, 5, 18, + 15, 3, 2, 11, + }, + // 0b01001001 case 73 + { + 10, 6, 5, 18, + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + }, + // 0b01001010 case 74 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + 10, 6, 5, 18, + }, + // 0b01001011 case 75 + { + 10, 6, 5, 18, + 2, 15, 1, 11, + 15, 13, 1, 11, + 13, 1, 11, 9, + 15, 12, 13, 11, + 11, 12, 13, 9, + 11, 12, 9, 8, + }, + // 0b01001100 case 76 + { + 14, 15, 3, 11, + 1, 14, 3, 11, + 1, 11, 3, 5, + 1, 14, 11, 5, + 5, 14, 11, 6, + 5, 14, 6, 18, + }, + // 0b01001101 case 77 + { + 12, 0, 15, 8, + 15, 8, 0, 11, + 14, 0, 1, 5, + 14, 15, 0, 11, + 14, 0, 5, 6, + 14, 11, 0, 6, + 14, 6, 5, 18, + }, + // 0b01001110 case 78 + { + 0, 13, 1, 9, + 1, 3, 0, 9, + 1, 3, 9, 11, + 1, 15, 3, 11, + 1, 14, 15, 11, + 1, 14, 11, 9, + 9, 14, 11, 5, + 14, 11, 5, 6, + 14, 6, 5, 18, + }, + // 0b01001111 case 79 + { + 15, 12, 13, 8, + 13, 15, 8, 11, + 13, 11, 8, 9, + 13, 14, 15, 9, + 14, 15, 9, 11, + 9, 14, 11, 5, + 14, 11, 5, 6, + 14, 6, 5, 18, + }, + // 0b01010000 case 80 + { + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01010001 case 81 + { + 10, 6, 5, 18, + 12, 0, 3, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b01010010 case 82 + { + 13, 1, 0, 9, + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01010011 case 83 + { + 10, 6, 5, 18, + 12, 13, 1, 9, + 3, 12, 1, 9, + 3, 9, 1, 7, + 3, 12, 9, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + }, + // 0b01010100 case 84 + { + 8, 4, 7, 16, + 14, 2, 1, 6, + 1, 14, 6, 5, + 5, 14, 6, 18, + }, + // 0b01010101 case 85 + { + 3, 12, 0, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + 1, 14, 2, 5, + 14, 2, 5, 6, + 5, 14, 6, 18, + }, + // 0b01010110 case 86 + { + 8, 4, 7, 16, + 0, 13, 2, 6, + 0, 13, 6, 9, + 13, 14, 2, 6, + 13, 14, 6, 9, + 14, 6, 9, 5, + 14, 6, 5, 18, + }, + // 0b01010111 case 87 + { + 13, 2, 3, 9, + 13, 3, 12, 9, + 13, 14, 2, 9, + 14, 2, 9, 6, + 3, 12, 9, 7, + 12, 9, 7, 4, + 14, 6, 9, 5, + 12, 4, 7, 16, + 14, 6, 5, 18, + }, + // 0b01011000 case 88 + { + 8, 4, 7, 16, + 10, 6, 5, 18, + 15, 3, 2, 11, + }, + // 0b01011001 case 89 + { + 10, 6, 5, 18, + 2, 15, 0, 4, + 2, 15, 4, 11, + 15, 12, 0, 4, + 15, 12, 4, 11, + 11, 12, 4, 7, + 7, 12, 4, 16, + }, + // 0b01011010 case 90 + { + 13, 1, 0, 9, + 2, 15, 3, 11, + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01011011 case 91 + { + 10, 6, 5, 18, + 15, 1, 2, 11, + 15, 13, 1, 11, + 13, 1, 11, 9, + 15, 12, 13, 11, + 12, 13, 11, 9, + 12, 9, 11, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + }, + // 0b01011100 case 92 + { + 8, 4, 7, 16, + 1, 15, 3, 5, + 15, 3, 5, 6, + 15, 3, 6, 11, + 1, 14, 15, 6, + 1, 14, 6, 5, + 14, 6, 5, 18, + }, + // 0b01011101 case 93 + { + 15, 0, 1, 11, + 15, 12, 0, 11, + 1, 14, 15, 11, + 11, 12, 0, 4, + 11, 1, 14, 5, + 11, 12, 4, 7, + 11, 5, 14, 6, + 14, 6, 5, 18, + 12, 4, 7, 16, + }, + // 0b01011110 case 94 + { + 8, 4, 7, 16, + 13, 3, 0, 9, + 13, 15, 3, 9, + 15, 3, 9, 11, + 13, 14, 15, 9, + 14, 15, 9, 11, + 14, 11, 9, 5, + 14, 11, 5, 6, + 14, 6, 5, 18, + }, + // 0b01011111 case 95 + { + 15, 12, 13, 11, + 11, 12, 13, 9, + 11, 12, 9, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + 13, 14, 15, 9, + 14, 15, 9, 11, + 9, 14, 11, 5, + 5, 14, 11, 6, + 14, 6, 5, 18, + }, + // 0b01100000 case 96 + { + 9, 10, 4, 17, + 10, 6, 4, 17, + 10, 6, 17, 18, + }, + // 0b01100001 case 97 + { + 12, 0, 3, 8, + 4, 9, 6, 17, + 9, 10, 6, 17, + 17, 10, 6, 18, + }, + // 0b01100010 case 98 + { + 0, 13, 1, 6, + 1, 10, 6, 18, + 13, 1, 6, 18, + 0, 13, 6, 4, + 13, 18, 6, 4, + 13, 18, 4, 17, + }, + // 0b01100011 case 99 + { + 3, 12, 1, 8, + 12, 13, 1, 8, + 8, 13, 1, 17, + 1, 8, 17, 4, + 1, 6, 8, 4, + 1, 4, 17, 6, + 1, 6, 17, 10, + 17, 10, 6, 18, + }, + // 0b01100100 case 100 + { + 1, 14, 2, 4, + 14, 2, 4, 6, + 1, 4, 9, 6, + 1, 14, 6, 9, + 14, 6, 9, 18, + 9, 18, 6, 4, + 4, 9, 18, 17, + }, + // 0b01100101 case 101 + { + 3, 12, 0, 8, + 1, 14, 2, 9, + 9, 14, 2, 4, + 14, 2, 4, 6, + 9, 14, 4, 17, + 14, 17, 4, 6, + 14, 6, 17, 18, + }, + // 0b01100110 case 102 + { + 0, 13, 2, 4, + 13, 14, 2, 4, + 14, 2, 4, 6, + 14, 18, 6, 4, + 14, 18, 4, 13, + 13, 18, 4, 17, + }, + // 0b01100111 case 103 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 13, 14, 2, 8, + 14, 2, 8, 4, + 13, 14, 8, 4, + 14, 2, 4, 6, + 13, 14, 4, 17, + 14, 4, 17, 6, + 14, 6, 17, 18, + }, + // 0b01101000 case 104 + { + 2, 15, 3, 11, + 4, 9, 6, 17, + 9, 10, 6, 17, + 10, 6, 17, 18, + }, + // 0b01101001 case 105 + { + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + 4, 9, 6, 17, + 9, 10, 6, 17, + 10, 6, 17, 18, + }, + // 0b01101010 case 106 + { + 2, 15, 3, 11, + 0, 13, 1, 6, + 0, 13, 6, 4, + 1, 10, 6, 4, + 13, 1, 4, 17, + 10, 6, 4, 18, + 17, 1, 4, 10, + 17, 10, 4, 18, + }, + // 0b01101011 case 107 + { + 15, 1, 2, 11, + 15, 12, 1, 11, + 12, 1, 11, 8, + 12, 13, 1, 8, + 8, 13, 1, 4, + 13, 1, 4, 17, + 1, 6, 4, 17, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01101100 case 108 + { + 1, 14, 3, 9, + 14, 15, 3, 9, + 15, 3, 9, 11, + 14, 15, 9, 11, + 14, 11, 9, 6, + 14, 6, 9, 18, + 9, 18, 6, 4, + 4, 9, 18, 17, + }, + // 0b01101101 case 109 + { + 12, 0, 1, 8, + 15, 12, 1, 8, + 15, 8, 1, 11, + 14, 15, 1, 11, + 1, 14, 11, 6, + 1, 14, 6, 18, + 1, 18, 6, 4, + 1, 18, 4, 17, + 1, 17, 4, 9, + }, + // 0b01101110 case 110 + { + 14, 15, 3, 11, + 0, 14, 3, 11, + 0, 13, 14, 11, + 0, 13, 11, 6, + 13, 14, 11, 6, + 13, 14, 6, 18, + 0, 13, 6, 4, + 13, 18, 6, 4, + 13, 18, 4, 17, + }, + // 0b01101111 case 111 + { + 15, 12, 13, 11, + 13, 14, 15, 11, + 12, 13, 11, 8, + 8, 13, 14, 4, + 14, 8, 4, 11, + 14, 11, 4, 6, + 13, 14, 4, 17, + 14, 4, 17, 6, + 14, 6, 17, 18, + }, + // 0b01110000 case 112 + { + 8, 9, 10, 7, + 9, 10, 7, 6, + 8, 9, 7, 16, + 9, 10, 6, 18, + 9, 7, 16, 17, + 9, 6, 7, 17, + 9, 18, 6, 17, + }, + // 0b01110001 case 113 + { + 12, 0, 3, 7, + 12, 0, 7, 16, + 0, 9, 10, 7, + 0, 9, 7, 16, + 9, 10, 16, 17, + 10, 7, 16, 17, + 10, 7, 17, 6, + 10, 6, 17, 18, + }, + // 0b01110010 case 114 + { + 0, 13, 1, 10, + 0, 13, 10, 8, + 13, 10, 8, 6, + 13, 6, 8, 7, + 13, 10, 6, 18, + 13, 7, 8, 16, + 13, 6, 7, 17, + 13, 18, 6, 17, + 13, 7, 16, 17, + }, + // 0b01110011 case 115 + { + 3, 12, 13, 7, + 12, 13, 7, 16, + 13, 1, 3, 7, + 13, 1, 16, 17, + 1, 7, 16, 6, + 1, 6, 16, 17, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01110100 case 116 + { + 1, 14, 2, 6, + 1, 14, 6, 18, + 1, 18, 6, 7, + 1, 8, 9, 16, + 1, 7, 8, 16, + 1, 18, 7, 16, + 1, 18, 16, 9, + 9, 18, 16, 17, + }, + // 0b01110101 case 117 + { + 3, 12, 0, 9, + 3, 12, 9, 7, + 12, 9, 7, 16, + 9, 7, 16, 17, + 9, 6, 7, 17, + 1, 14, 2, 9, + 14, 2, 9, 6, + 14, 6, 9, 17, + 14, 6, 17, 18, + }, + // 0b01110110 case 118 + { + 13, 14, 2, 6, + 0, 13, 2, 6, + 13, 14, 6, 18, + 0, 13, 18, 17, + 0, 17, 18, 6, + 0, 17, 6, 7, + 0, 17, 7, 16, + 0, 7, 8, 16, + }, + // 0b01110111 case 119 + { + 12, 2, 3, 7, + 12, 14, 2, 7, + 14, 2, 7, 6, + 12, 13, 14, 7, + 12, 13, 7, 16, + 14, 6, 7, 18, + 14, 18, 7, 16, + 13, 14, 16, 18, + 13, 18, 16, 17, + }, + // 0b01111000 case 120 + { + 2, 15, 3, 11, + 8, 9, 10, 7, + 9, 10, 7, 6, + 9, 10, 6, 18, + 8, 9, 7, 16, + 9, 18, 6, 17, + 9, 6, 7, 17, + 9, 7, 16, 17, + }, + // 0b01111001 case 121 + { + 15, 0, 2, 7, + 15, 7, 2, 11, + 15, 12, 0, 7, + 12, 0, 7, 16, + 16, 0, 7, 9, + 16, 9, 7, 17, + 9, 10, 7, 17, + 10, 7, 17, 18, + 10, 7, 18, 6, + }, + // 0b01111010 case 122 + { + 15, 3, 2, 11, + 0, 13, 1, 10, + 0, 13, 10, 8, + 13, 10, 8, 6, + 8, 13, 6, 7, + 13, 6, 7, 17, + 13, 10, 6, 17, + 13, 7, 8, 17, + 17, 10, 6, 18, + 17, 7, 8, 16, + }, + // 0b01111011 case 123 + { + 15, 1, 2, 11, + 15, 12, 1, 11, + 12, 13, 1, 11, + 13, 1, 11, 7, + 12, 13, 11, 7, + 12, 13, 7, 16, + 13, 7, 16, 17, + 13, 1, 7, 17, + 1, 7, 17, 6, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01111100 case 124 + { + 3, 11, 6, 15, + 1, 15, 3, 6, + 1, 14, 15, 6, + 1, 14, 6, 18, + 1, 18, 6, 9, + 9, 18, 6, 17, + 8, 9, 6, 17, + 8, 17, 6, 7, + 8, 17, 7, 16, + }, + // 0b01111101 case 125 + { + 12, 0, 1, 9, + 12, 1, 14, 9, + 12, 14, 15, 9, + 12, 9, 15, 17, + 14, 15, 9, 17, + 15, 12, 17, 16, + 15, 17, 14, 18, + 15, 16, 17, 7, + 15, 18, 17, 6, + 15, 7, 17, 11, + 15, 17, 6, 11, + 11, 6, 7, 17, + }, + // 0b01111110 case 126 + { + 15, 3, 0, 11, + 14, 15, 0, 11, + 0, 14, 11, 6, + 0, 13, 14, 6, + 13, 14, 6, 18, + 0, 13, 18, 17, + 0, 18, 6, 17, + 0, 17, 6, 7, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b01111111 case 127 + { + 6, 7, 11, 15, + 12, 15, 13, 7, + 13, 14, 15, 7, + 14, 15, 7, 6, + 13, 14, 7, 6, + 13, 14, 6, 18, + 12, 13, 7, 16, + 13, 18, 6, 17, + 13, 6, 7, 17, + 13, 7, 16, 17, + }, + // 0b10000000 case 128 + { + 11, 7, 6, 19, + }, + // 0b10000001 case 129 + { + 3, 12, 0, 8, + 11, 7, 6, 19, + }, + // 0b10000010 case 130 + { + 0, 13, 1, 9, + 11, 7, 6, 19, + }, + // 0b10000011 case 131 + { + 11, 7, 6, 19, + 3, 12, 1, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + }, + // 0b10000100 case 132 + { + 1, 14, 2, 10, + 11, 7, 6, 19, + }, + // 0b10000101 case 133 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 11, 7, 6, 19, + }, + // 0b10000110 case 134 + { + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 10, + 11, 7, 6, 19, + }, + // 0b10000111 case 135 + { + 12, 2, 3, 8, + 12, 14, 2, 8, + 14, 2, 8, 10, + 12, 13, 14, 8, + 13, 14, 8, 10, + 13, 10, 8, 9, + 11, 7, 6, 19, + }, + // 0b10001000 case 136 + { + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001001 case 137 + { + 2, 15, 0, 6, + 15, 12, 0, 6, + 12, 0, 6, 7, + 12, 0, 7, 8, + 15, 12, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001010 case 138 + { + 0, 13, 1, 9, + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001011 case 139 + { + 12, 13, 1, 9, + 12, 9, 1, 8, + 12, 1, 2, 8, + 2, 8, 1, 7, + 2, 7, 1, 6, + 2, 15, 12, 8, + 2, 15, 8, 7, + 2, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10001100 case 140 + { + 15, 3, 1, 7, + 14, 15, 1, 7, + 1, 14, 7, 6, + 1, 14, 6, 10, + 14, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10001101 case 141 + { + 14, 0, 1, 10, + 14, 12, 0, 10, + 12, 0, 10, 8, + 14, 15, 12, 10, + 15, 12, 10, 8, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + }, + // 0b10001110 case 142 + { + 0, 13, 14, 9, + 14, 0, 9, 10, + 14, 15, 0, 10, + 15, 3, 0, 10, + 10, 3, 0, 7, + 10, 15, 3, 7, + 10, 15, 7, 6, + 6, 15, 7, 19, + }, + // 0b10001111 case 143 + { + 14, 15, 12, 8, + 14, 15, 8, 10, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + 12, 13, 14, 10, + 12, 13, 10, 8, + 8, 13, 10, 9, + }, + // 0b10010000 case 144 + { + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010001 case 145 + { + 3, 12, 0, 4, + 3, 4, 0, 6, + 12, 4, 16, 6, + 3, 12, 6, 16, + 3, 16, 6, 19, + 3, 19, 6, 11, + }, + // 0b10010010 case 146 + { + 0, 13, 1, 9, + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010011 case 147 + { + 3, 13, 1, 9, + 3, 12, 13, 9, + 3, 12, 9, 6, + 12, 9, 6, 4, + 3, 12, 4, 16, + 3, 16, 4, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10010100 case 148 + { + 1, 14, 2, 10, + 11, 8, 6, 19, + 8, 4, 6, 19, + 8, 4, 19, 16, + }, + // 0b10010101 case 149 + { + 1, 14, 2, 10, + 3, 12, 0, 11, + 12, 0, 11, 6, + 12, 6, 11, 19, + 0, 6, 19, 4, + 12, 0, 19, 4, + 12, 4, 19, 16, + }, + // 0b10010110 case 150 + { + 13, 14, 0, 9, + 14, 2, 0, 9, + 14, 2, 9, 10, + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010111 case 151 + { + 3, 14, 2, 10, + 3, 13, 14, 10, + 3, 13, 10, 9, + 3, 12, 13, 9, + 3, 12, 9, 4, + 3, 12, 4, 16, + 3, 16, 4, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10011000 case 152 + { + 2, 15, 3, 8, + 2, 15, 8, 4, + 15, 8, 4, 16, + 2, 15, 4, 6, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011001 case 153 + { + 12, 0, 2, 4, + 15, 12, 2, 4, + 2, 15, 4, 6, + 12, 4, 15, 16, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011010 case 154 + { + 0, 13, 1, 9, + 2, 15, 3, 8, + 2, 15, 8, 4, + 15, 8, 4, 16, + 2, 15, 4, 6, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011011 case 155 + { + 2, 13, 1, 9, + 2, 13, 9, 4, + 12, 13, 2, 4, + 15, 12, 2, 4, + 2, 15, 4, 6, + 15, 12, 4, 16, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011100 case 156 + { + 14, 3, 1, 8, + 14, 8, 1, 10, + 14, 15, 3, 8, + 14, 15, 8, 10, + 10, 15, 8, 6, + 15, 8, 6, 19, + 6, 19, 8, 4, + 19, 8, 4, 16, + }, + // 0b10011101 case 157 + { + 14, 0, 1, 10, + 14, 15, 0, 10, + 15, 12, 0, 10, + 12, 0, 10, 6, + 15, 12, 10, 6, + 12, 0, 6, 4, + 15, 12, 6, 19, + 12, 4, 6, 19, + 12, 4, 19, 16, + }, + // 0b10011110 case 158 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 10, + 14, 15, 3, 10, + 15, 3, 10, 6, + 15, 3, 6, 19, + 3, 6, 19, 4, + 3, 4, 19, 8, + 8, 4, 19, 16, + }, + // 0b10011111 case 159 + { + 12, 13, 14, 10, + 12, 13, 10, 9, + 12, 14, 15, 10, + 15, 9, 10, 6, + 15, 12, 9, 6, + 12, 9, 6, 4, + 15, 12, 6, 19, + 12, 6, 19, 4, + 12, 4, 19, 16, + }, + // 0b10100000 case 160 + { + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100001 case 161 + { + 3, 12, 0, 8, + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100010 case 162 + { + 0, 13, 1, 4, + 13, 1, 4, 5, + 4, 13, 5, 17, + 11, 7, 6, 19, + }, + // 0b10100011 case 163 + { + 3, 13, 1, 5, + 3, 12, 13, 5, + 12, 13, 5, 17, + 3, 17, 5, 4, + 3, 12, 17, 4, + 3, 12, 4, 8, + 11, 7, 6, 19, + }, + // 0b10100100 case 164 + { + 1, 14, 2, 10, + 11, 7, 6, 19, + 9, 5, 4, 17, + }, + // 0b10100101 case 165 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100110 case 166 + { + 14, 2, 0, 10, + 13, 14, 0, 10, + 0, 13, 10, 5, + 0, 13, 5, 4, + 13, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100111 case 167 + { + 11, 7, 6, 19, + 3, 14, 2, 10, + 3, 12, 14, 10, + 3, 12, 10, 8, + 12, 13, 14, 10, + 12, 13, 10, 8, + 8, 13, 10, 5, + 8, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b10101000 case 168 + { + 9, 5, 4, 17, + 2, 15, 3, 6, + 15, 3, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101001 case 169 + { + 9, 5, 4, 17, + 2, 12, 0, 6, + 12, 0, 6, 7, + 12, 0, 7, 8, + 2, 15, 12, 6, + 15, 12, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101010 case 170 + { + 0, 13, 1, 4, + 13, 1, 4, 5, + 13, 5, 4, 17, + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10101011 case 171 + { + 2, 12, 1, 8, + 12, 13, 1, 8, + 2, 15, 12, 8, + 8, 13, 1, 5, + 8, 13, 5, 4, + 4, 13, 5, 17, + 2, 15, 8, 6, + 15, 8, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101100 case 172 + { + 9, 5, 4, 17, + 1, 15, 3, 7, + 1, 14, 15, 7, + 1, 14, 7, 6, + 1, 14, 6, 10, + 14, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10101101 case 173 + { + 9, 5, 4, 17, + 1, 12, 0, 8, + 14, 12, 1, 8, + 14, 15, 12, 8, + 14, 8, 1, 10, + 14, 15, 8, 10, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + }, + // 0b10101110 case 174 + { + 13, 14, 0, 10, + 14, 3, 0, 10, + 14, 15, 3, 10, + 0, 13, 10, 5, + 0, 5, 10, 4, + 0, 13, 5, 4, + 13, 5, 4, 17, + 15, 3, 10, 7, + 15, 7, 10, 6, + 15, 7, 6, 19, + }, + // 0b10101111 case 175 + { + 12, 13, 14, 10, + 12, 14, 15, 10, + 12, 13, 10, 8, + 10, 15, 12, 8, + 10, 15, 8, 6, + 15, 8, 6, 7, + 15, 7, 6, 19, + 13, 10, 8, 4, + 13, 10, 4, 5, + 13, 5, 4, 17, + }, + // 0b10110000 case 176 + { + 11, 8, 9, 5, + 11, 8, 5, 6, + 8, 9, 5, 17, + 8, 6, 11, 19, + 8, 17, 5, 16, + 8, 5, 6, 16, + 8, 6, 19, 16, + }, + // 0b10110001 case 177 + { + 12, 0, 3, 11, + 11, 12, 0, 9, + 11, 12, 9, 6, + 12, 9, 6, 5, + 12, 6, 11, 19, + 12, 9, 5, 17, + 12, 17, 5, 16, + 12, 5, 6, 16, + 12, 6, 19, 16, + }, + // 0b10110010 case 178 + { + 0, 13, 1, 5, + 0, 13, 5, 17, + 0, 17, 5, 6, + 0, 17, 6, 11, + 11, 17, 6, 19, + 0, 17, 11, 19, + 0, 19, 11, 8, + 0, 17, 19, 8, + 8, 17, 19, 16, + }, + // 0b10110011 case 179 + { + 3, 13, 1, 5, + 3, 12, 13, 5, + 12, 13, 5, 17, + 3, 12, 17, 16, + 3, 17, 5, 16, + 3, 16, 5, 6, + 3, 16, 6, 11, + 16, 6, 11, 19, + }, + // 0b10110100 case 180 + { + 11, 8, 9, 5, + 11, 8, 5, 6, + 8, 9, 5, 17, + 8, 17, 5, 16, + 8, 5, 6, 16, + 8, 6, 11, 19, + 8, 6, 19, 16, + 1, 14, 2, 10, + }, + // 0b10110101 case 181 + { + 1, 14, 2, 10, + 3, 12, 0, 9, + 3, 12, 9, 11, + 11, 12, 9, 5, + 11, 12, 5, 6, + 12, 9, 5, 17, + 11, 12, 6, 19, + 12, 17, 5, 16, + 12, 5, 6, 16, + 12, 6, 19, 16, + }, + // 0b10110110 case 182 + { + 13, 14, 2, 10, + 0, 13, 2, 10, + 0, 10, 2, 5, + 0, 13, 10, 5, + 0, 13, 5, 17, + 0, 17, 5, 8, + 8, 17, 5, 16, + 11, 8, 5, 16, + 11, 16, 5, 6, + 11, 16, 6, 19, + }, + // 0b10110111 case 183 + { + 3, 14, 2, 10, + 3, 13, 14, 10, + 3, 12, 13, 10, + 3, 12, 10, 5, + 12, 13, 10, 5, + 12, 13, 5, 17, + 3, 12, 17, 16, + 3, 17, 5, 16, + 3, 16, 5, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10111000 case 184 + { + 8, 9, 5, 17, + 8, 17, 5, 16, + 2, 15, 3, 8, + 2, 15, 8, 5, + 2, 15, 5, 6, + 15, 8, 5, 6, + 6, 8, 5, 16, + 6, 15, 8, 19, + 6, 19, 8, 16, + }, + // 0b10111001 case 185 + { + 2, 15, 0, 6, + 15, 12, 0, 6, + 15, 12, 6, 19, + 12, 0, 19, 16, + 0, 6, 19, 16, + 0, 6, 16, 5, + 0, 5, 16, 9, + 16, 9, 5, 17, + }, + // 0b10111010 case 186 + { + 0, 13, 1, 8, + 13, 1, 8, 5, + 8, 13, 5, 17, + 8, 17, 5, 16, + 8, 16, 5, 6, + 2, 15, 3, 8, + 2, 15, 8, 6, + 15, 8, 6, 16, + 15, 16, 6, 19, + }, + // 0b10111011 case 187 + { + 2, 13, 1, 5, + 2, 12, 13, 5, + 12, 13, 5, 17, + 12, 17, 5, 16, + 12, 2, 15, 5, + 2, 15, 5, 6, + 15, 12, 5, 16, + 15, 16, 5, 6, + 15, 16, 6, 19, + }, + // 0b10111100 case 188 + { + 14, 3, 1, 6, + 1, 14, 6, 10, + 14, 15, 3, 6, + 15, 3, 6, 19, + 3, 6, 19, 8, + 8, 6, 19, 16, + 8, 6, 16, 9, + 9, 6, 16, 5, + 9, 5, 16, 17, + }, + // 0b10111101 case 189 + { + 14, 0, 1, 10, + 14, 12, 0, 10, + 14, 15, 12, 10, + 12, 0, 10, 6, + 10, 15, 12, 6, + 6, 15, 12, 19, + 12, 0, 19, 16, + 0, 6, 19, 16, + 0, 6, 16, 5, + 0, 5, 16, 9, + 16, 9, 5, 17, + }, + // 0b10111110 case 190 + { + 0, 15, 3, 8, + 0, 14, 15, 8, + 0, 13, 14, 8, + 8, 14, 15, 16, + 14, 15, 16, 19, + 13, 14, 8, 16, + 13, 14, 16, 17, + 14, 16, 17, 5, + 14, 16, 5, 10, + 10, 16, 5, 6, + 14, 19, 16, 10, + 10, 19, 16, 6, + }, + // 0b10111111 case 191 + { + 0, 15, 12, 8, + 0, 14, 15, 8, + 0, 13, 14, 8, + 8, 14, 15, 16, + 14, 15, 16, 19, + 13, 14, 8, 16, + 13, 14, 16, 17, + 14, 16, 17, 5, + 14, 16, 5, 10, + 10, 16, 5, 6, + 14, 19, 16, 10, + 10, 19, 16, 6, + }, + // 0b11000000 case 192 + { + 10, 11, 5, 18, + 18, 11, 5, 7, + 11, 7, 18, 19, + }, + // 0b11000001 case 193 + { + 3, 12, 0, 8, + 5, 10, 11, 18, + 5, 18, 11, 7, + 11, 7, 18, 19, + }, + // 0b11000010 case 194 + { + 0, 13, 1, 9, + 10, 11, 5, 18, + 11, 7, 5, 18, + 11, 7, 18, 19, + }, + // 0b11000011 case 195 + { + 12, 1, 3, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + 10, 11, 5, 18, + 11, 7, 5, 18, + 11, 7, 18, 19, + }, + // 0b11000100 case 196 + { + 1, 14, 2, 7, + 1, 14, 7, 5, + 14, 2, 5, 18, + 2, 7, 5, 18, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11000101 case 197 + { + 1, 14, 2, 7, + 1, 14, 7, 5, + 14, 2, 5, 18, + 2, 7, 5, 18, + 2, 7, 18, 11, + 11, 7, 18, 19, + 3, 12, 0, 8, + }, + // 0b11000110 case 198 + { + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 5, + 14, 2, 5, 18, + 2, 9, 5, 7, + 2, 5, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11000111 case 199 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 8, 13, 2, 9, + 13, 14, 2, 9, + 9, 14, 2, 5, + 14, 2, 5, 18, + 2, 5, 18, 7, + 7, 18, 2, 11, + 18, 11, 7, 19, + }, + // 0b11001000 case 200 + { + 2, 15, 3, 10, + 15, 3, 10, 5, + 5, 10, 15, 18, + 5, 15, 3, 7, + 5, 18, 15, 7, + 18, 15, 7, 19, + }, + // 0b11001001 case 201 + { + 12, 0, 2, 8, + 15, 12, 2, 8, + 2, 15, 8, 7, + 2, 15, 7, 19, + 2, 7, 8, 5, + 2, 19, 7, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001010 case 202 + { + 0, 13, 1, 9, + 2, 15, 3, 5, + 15, 3, 5, 7, + 2, 15, 7, 19, + 2, 7, 5, 19, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001011 case 203 + { + 2, 13, 1, 9, + 2, 12, 13, 9, + 2, 12, 9, 8, + 2, 15, 12, 8, + 2, 15, 8, 7, + 2, 15, 7, 19, + 2, 19, 7, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001100 case 204 + { + 1, 14, 3, 5, + 14, 15, 3, 5, + 15, 3, 5, 7, + 14, 15, 5, 18, + 15, 7, 5, 18, + 15, 7, 18, 19, + }, + // 0b11001101 case 205 + { + 1, 12, 0, 8, + 1, 15, 12, 8, + 1, 15, 8, 7, + 1, 14, 15, 7, + 14, 15, 7, 19, + 14, 7, 1, 5, + 14, 7, 5, 19, + 14, 19, 5, 18, + }, + // 0b11001110 case 206 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 5, + 14, 15, 3, 5, + 14, 15, 5, 18, + 15, 3, 5, 7, + 15, 7, 5, 18, + 15, 7, 18, 19, + }, + // 0b11001111 case 207 + { + 15, 12, 13, 8, + 13, 15, 8, 9, + 14, 15, 13, 9, + 15, 8, 9, 7, + 14, 15, 9, 7, + 14, 7, 9, 5, + 15, 7, 14, 19, + 14, 19, 7, 5, + 14, 19, 5, 18, + }, + // 0b11010000 case 208 + { + 10, 11, 8, 4, + 10, 11, 4, 5, + 11, 8, 4, 16, + 11, 5, 10, 18, + 11, 16, 4, 19, + 11, 4, 5, 19, + 11, 5, 18, 19, + }, + // 0b11010001 case 209 + { + 3, 12, 0, 5, + 12, 0, 5, 4, + 12, 4, 5, 16, + 3, 12, 5, 16, + 3, 16, 5, 11, + 11, 16, 5, 19, + 11, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11010010 case 210 + { + 0, 13, 1, 9, + 10, 11, 8, 4, + 10, 11, 4, 5, + 10, 11, 5, 18, + 11, 8, 4, 16, + 11, 5, 18, 19, + 11, 4, 5, 19, + 11, 16, 4, 19, + }, + // 0b11010011 case 211 + { + 3, 13, 1, 4, + 13, 1, 4, 9, + 3, 12, 13, 4, + 3, 12, 4, 16, + 3, 16, 4, 11, + 11, 16, 4, 19, + 10, 11, 4, 19, + 10, 19, 4, 5, + 10, 19, 5, 18, + }, + // 0b11010100 case 212 + { + 1, 14, 2, 5, + 14, 2, 5, 18, + 2, 5, 18, 4, + 2, 4, 18, 8, + 2, 8, 18, 11, + 18, 8, 4, 16, + 18, 8, 16, 11, + 18, 11, 16, 19, + }, + // 0b11010101 case 213 + { + 12, 0, 3, 11, + 12, 0, 11, 4, + 12, 4, 11, 16, + 4, 11, 16, 19, + 11, 19, 4, 5, + 11, 19, 5, 18, + 1, 14, 2, 11, + 1, 14, 11, 5, + 14, 11, 5, 18, + }, + // 0b11010110 case 214 + { + 13, 2, 0, 5, + 0, 13, 5, 9, + 13, 14, 2, 5, + 5, 14, 2, 18, + 5, 18, 2, 11, + 5, 18, 11, 19, + 5, 11, 8, 19, + 8, 5, 19, 4, + 8, 4, 19, 16, + }, + // 0b11010111 case 215 + { + 3, 2, 11, 19, + 3, 14, 2, 19, + 3, 12, 14, 19, + 12, 13, 14, 19, + 12, 13, 19, 16, + 13, 14, 16, 9, + 9, 14, 16, 4, + 14, 19, 16, 4, + 14, 4, 9, 5, + 14, 19, 4, 5, + 14, 19, 5, 18, + }, + // 0b11011000 case 216 + { + 2, 15, 3, 10, + 15, 3, 10, 8, + 10, 15, 8, 5, + 15, 8, 5, 4, + 15, 5, 10, 18, + 15, 8, 4, 16, + 15, 4, 5, 19, + 15, 16, 4, 19, + 15, 5, 18, 19, + }, + // 0b11011001 case 217 + { + 2, 12, 0, 4, + 2, 15, 12, 4, + 15, 12, 4, 16, + 2, 15, 16, 19, + 2, 19, 16, 4, + 2, 19, 4, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11011010 case 218 + { + 0, 13, 1, 9, + 2, 15, 3, 10, + 15, 3, 10, 8, + 10, 15, 8, 5, + 5, 15, 8, 4, + 15, 5, 10, 18, + 15, 4, 5, 19, + 15, 8, 4, 16, + 15, 5, 18, 19, + 15, 16, 4, 19, + }, + // 0b11011011 case 219 + { + 13, 1, 2, 9, + 12, 13, 2, 9, + 12, 2, 15, 9, + 15, 9, 2, 4, + 15, 12, 9, 4, + 15, 12, 4, 16, + 15, 16, 2, 19, + 2, 16, 4, 19, + 2, 19, 4, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11011100 case 220 + { + 1, 14, 3, 5, + 14, 15, 3, 5, + 14, 15, 5, 18, + 15, 3, 5, 8, + 15, 8, 5, 4, + 15, 8, 4, 16, + 15, 16, 4, 19, + 15, 4, 5, 19, + 15, 5, 18, 19, + }, + // 0b11011101 case 221 + { + 14, 0, 1, 5, + 14, 15, 0, 5, + 14, 15, 5, 18, + 15, 12, 0, 5, + 12, 0, 5, 4, + 15, 12, 18, 19, + 12, 4, 5, 16, + 12, 5, 18, 16, + 12, 18, 19, 16, + }, + // 0b11011110 case 222 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 5, + 14, 3, 5, 18, + 14, 15, 3, 18, + 15, 3, 18, 19, + 3, 18, 19, 5, + 3, 5, 19, 4, + 3, 4, 19, 8, + 8, 4, 19, 16, + }, + // 0b11011111 case 223 + { + 14, 12, 13, 9, + 14, 15, 12, 9, + 14, 15, 9, 5, + 14, 15, 5, 18, + 15, 9, 5, 4, + 15, 12, 9, 4, + 15, 12, 4, 16, + 15, 16, 4, 19, + 15, 4, 5, 19, + 15, 5, 18, 19, + }, + // 0b11100000 case 224 + { + 9, 10, 11, 7, + 9, 10, 7, 4, + 10, 11, 7, 19, + 10, 4, 9, 17, + 10, 19, 7, 18, + 10, 7, 4, 18, + 10, 4, 17, 18, + }, + // 0b11100001 case 225 + { + 3, 12, 0, 8, + 9, 10, 11, 7, + 9, 10, 7, 4, + 10, 11, 7, 19, + 10, 4, 9, 17, + 10, 19, 7, 18, + 10, 7, 4, 18, + 10, 4, 17, 18, + }, + // 0b11100010 case 226 + { + 0, 13, 1, 4, + 13, 1, 4, 17, + 1, 4, 17, 10, + 10, 4, 17, 18, + 1, 4, 10, 11, + 10, 11, 4, 18, + 18, 11, 4, 7, + 18, 11, 7, 19, + }, + // 0b11100011 case 227 + { + 12, 1, 3, 4, + 12, 4, 3, 8, + 12, 13, 1, 4, + 13, 1, 4, 17, + 1, 4, 17, 10, + 10, 4, 17, 18, + 10, 11, 4, 18, + 11, 4, 18, 7, + 11, 7, 18, 19, + }, + // 0b11100100 case 228 + { + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 4, + 14, 11, 4, 7, + 14, 11, 7, 19, + 14, 4, 9, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + }, + // 0b11100101 case 229 + { + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 4, + 14, 11, 4, 7, + 14, 11, 7, 19, + 14, 4, 9, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + 3, 12, 0, 8, + }, + // 0b11100110 case 230 + { + 0, 13, 2, 4, + 13, 14, 2, 4, + 13, 14, 4, 17, + 14, 2, 17, 18, + 2, 4, 17, 18, + 2, 4, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11100111 case 231 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 13, 2, 8, 4, + 13, 14, 2, 4, + 13, 14, 4, 17, + 14, 2, 17, 18, + 2, 4, 17, 18, + 2, 4, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11101000 case 232 + { + 2, 15, 3, 7, + 2, 15, 7, 19, + 2, 19, 7, 4, + 2, 19, 4, 9, + 9, 19, 4, 17, + 2, 19, 9, 10, + 9, 10, 19, 17, + 10, 19, 17, 18, + }, + // 0b11101001 case 233 + { + 2, 12, 0, 7, + 12, 0, 7, 8, + 2, 15, 12, 7, + 2, 15, 7, 19, + 2, 19, 7, 10, + 10, 19, 7, 18, + 9, 10, 7, 18, + 9, 18, 7, 4, + 9, 18, 4, 17, + }, + // 0b11101010 case 234 + { + 0, 13, 1, 10, + 0, 13, 10, 17, + 0, 17, 10, 4, + 10, 4, 17, 18, + 10, 7, 4, 18, + 2, 15, 3, 10, + 15, 3, 10, 7, + 10, 15, 7, 18, + 15, 7, 18, 19, + }, + // 0b11101011 case 235 + { + 13, 1, 2, 10, + 13, 2, 15, 10, + 13, 15, 12, 10, + 12, 13, 10, 18, + 10, 15, 12, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 8, + 12, 18, 19, 8, + 8, 17, 18, 4, + 8, 4, 18, 7, + 19, 8, 18, 7, + }, + // 0b11101100 case 236 + { + 1, 15, 3, 7, + 1, 14, 15, 7, + 14, 15, 7, 19, + 1, 14, 19, 18, + 1, 18, 19, 7, + 1, 18, 7, 4, + 1, 18, 4, 9, + 9, 18, 4, 17, + }, + // 0b11101101 case 237 + { + 1, 12, 0, 8, + 1, 15, 12, 8, + 1, 14, 15, 8, + 1, 14, 8, 7, + 14, 15, 8, 7, + 14, 15, 7, 19, + 1, 14, 19, 18, + 1, 18, 19, 7, + 1, 18, 7, 4, + 4, 1, 18, 9, + 9, 18, 4, 17, + }, + // 0b11101110 case 238 + { + 13, 3, 0, 4, + 13, 15, 3, 4, + 15, 3, 4, 7, + 13, 14, 15, 7, + 13, 14, 7, 4, + 14, 15, 7, 19, + 13, 14, 4, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + }, + // 0b11101111 case 239 + { + 14, 15, 12, 18, + 12, 13, 14, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 8, + 12, 18, 19, 8, + 8, 17, 18, 4, + 18, 8, 4, 7, + 19, 8, 18, 7, + }, + // 0b11110000 case 240 + { + 9, 10, 11, 18, + 8, 9, 11, 18, + 8, 9, 18, 17, + 18, 11, 8, 19, + 8, 17, 18, 16, + 8, 18, 19, 16, + }, + // 0b11110001 case 241 + { + 3, 12, 0, 11, + 12, 0, 11, 9, + 11, 12, 9, 16, + 9, 10, 11, 16, + 10, 11, 16, 19, + 9, 10, 16, 17, + 10, 19, 16, 18, + 10, 16, 17, 18, + }, + // 0b11110010 case 242 + { + 0, 13, 1, 10, + 0, 13, 10, 8, + 8, 13, 10, 17, + 8, 17, 10, 18, + 8, 17, 18, 16, + 11, 8, 10, 16, + 11, 16, 10, 18, + 11, 16, 18, 19, + }, + // 0b11110011 case 243 + { + 12, 1, 3, 11, + 12, 13, 1, 11, + 13, 1, 11, 10, + 11, 13, 10, 18, + 11, 13, 18, 19, + 12, 13, 11, 19, + 12, 13, 18, 17, + 12, 17, 18, 19, + 12, 17, 19, 16, + }, + // 0b11110100 case 244 + { + 1, 14, 2, 11, + 1, 14, 11, 9, + 14, 11, 9, 18, + 11, 9, 18, 19, + 9, 18, 19, 17, + 8, 9, 11, 19, + 8, 9, 19, 17, + 8, 17, 19, 16, + }, + // 0b11110101 case 245 + { + 3, 12, 0, 11, + 12, 0, 11, 9, + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 18, + 12, 9, 11, 19, + 9, 18, 11, 19, + 12, 9, 19, 16, + 9, 18, 19, 17, + 9, 19, 16, 17, + }, + // 0b11110110 case 246 + { + 0, 13, 2, 8, + 13, 2, 8, 11, + 13, 14, 2, 11, + 13, 14, 11, 19, + 13, 11, 8, 19, + 13, 19, 8, 16, + 13, 14, 19, 18, + 13, 19, 16, 17, + 13, 18, 19, 17, + }, + // 0b11110111 case 247 + { + 12, 2, 3, 11, + 12, 14, 2, 11, + 12, 13, 14, 11, + 13, 14, 11, 18, + 12, 13, 11, 18, + 12, 18, 11, 19, + 12, 13, 18, 17, + 12, 18, 19, 16, + 12, 17, 18, 16, + }, + // 0b11111000 case 248 + { + 2, 15, 3, 10, + 15, 3, 10, 8, + 15, 8, 10, 19, + 8, 10, 19, 16, + 16, 10, 19, 18, + 8, 9, 10, 16, + 16, 9, 10, 18, + 9, 18, 16, 17, + }, + // 0b11111001 case 249 + { + 2, 15, 0, 10, + 15, 12, 0, 10, + 12, 0, 10, 9, + 10, 15, 9, 18, + 15, 12, 9, 18, + 12, 9, 18, 17, + 18, 15, 12, 19, + 12, 17, 18, 19, + 12, 17, 19, 16, + }, + // 0b11111010 case 250 + { + 0, 13, 1, 8, + 13, 1, 8, 10, + 8, 13, 10, 16, + 13, 10, 16, 18, + 13, 18, 16, 17, + 2, 15, 3, 10, + 15, 3, 10, 8, + 15, 8, 10, 18, + 15, 8, 18, 16, + 15, 16, 18, 19, + }, + // 0b11111011 case 251 + { + 2, 1, 10, 18, + 2, 15, 1, 18, + 15, 13, 1, 18, + 15, 12, 13, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 16, + 12, 18, 19, 16, + }, + // 0b11111100 case 252 + { + 1, 14, 3, 9, + 14, 3, 9, 8, + 14, 15, 3, 8, + 9, 14, 8, 17, + 14, 15, 8, 17, + 17, 15, 8, 16, + 14, 15, 17, 18, + 15, 17, 18, 19, + 15, 16, 17, 19, + }, + // 0b11111101 case 253 + { + 1, 0, 9, 17, + 14, 0, 1, 17, + 14, 12, 0, 17, + 14, 15, 12, 17, + 14, 15, 17, 18, + 15, 12, 17, 16, + 15, 17, 18, 19, + 15, 16, 17, 19, + }, + // 0b11111110 case 254 + { + 0, 3, 8, 16, + 13, 3, 0, 16, + 13, 15, 3, 16, + 13, 14, 15, 16, + 13, 14, 16, 17, + 14, 15, 16, 19, + 14, 16, 17, 18, + 14, 19, 16, 18, + }, + // 0b11111111 case 255 + { + 12, 14, 15, 19, + 12, 13, 14, 19, + 12, 13, 19, 16, + 13, 14, 19, 18, + 13, 18, 19, 17, + 13, 19, 16, 17, + }, } //----------------------------------------------------------------------------- From f252570457751547fe36d1dd81ace48599906f4f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 28 May 2023 17:20:14 +0330 Subject: [PATCH 442/775] Fix wrong points order of tetrahedra elements --- render/march3fetet4.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/render/march3fetet4.go b/render/march3fetet4.go index f3e55fec6..4605a6671 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -575,8 +575,8 @@ var mcTetrahedronTable = [256][]int{ // 0b00111011 case 59 { 12, 13, 1, 17, - 12, 1, 17, 5, - 12, 1, 5, 7, + 12, 17, 1, 5, + 12, 5, 1, 7, 12, 17, 5, 7, 12, 17, 7, 16, 2, 12, 1, 7, @@ -598,7 +598,7 @@ var mcTetrahedronTable = [256][]int{ 0, 17, 5, 7, 0, 17, 7, 16, 0, 16, 7, 12, - 12, 0, 7, 11, + 12, 0, 11, 7, 14, 0, 1, 10, 12, 0, 15, 11, 14, 15, 0, 11, @@ -948,7 +948,7 @@ var mcTetrahedronTable = [256][]int{ 9, 14, 2, 4, 14, 2, 4, 6, 9, 14, 4, 17, - 14, 17, 4, 6, + 14, 6, 4, 17, 14, 6, 17, 18, }, // 0b01100110 case 102 @@ -1220,7 +1220,7 @@ var mcTetrahedronTable = [256][]int{ 15, 12, 17, 16, 15, 17, 14, 18, 15, 16, 17, 7, - 15, 18, 17, 6, + 15, 17, 18, 6, 15, 7, 17, 11, 15, 17, 6, 11, 11, 6, 7, 17, @@ -1241,7 +1241,7 @@ var mcTetrahedronTable = [256][]int{ // 0b01111111 case 127 { 6, 7, 11, 15, - 12, 15, 13, 7, + 12, 13, 15, 7, 13, 14, 15, 7, 14, 15, 7, 6, 13, 14, 7, 6, @@ -1386,7 +1386,7 @@ var mcTetrahedronTable = [256][]int{ { 3, 12, 0, 4, 3, 4, 0, 6, - 12, 4, 16, 6, + 12, 4, 6, 16, 3, 12, 6, 16, 3, 16, 6, 19, 3, 19, 6, 11, From 2d15807a280810c190029e445877246e7bf861eb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 29 May 2023 12:39:35 +0330 Subject: [PATCH 443/775] Check for bad elements? --- render/finiteelements/mesh/inp.go | 7 +++++++ render/finiteelements/mesh/mesh.go | 2 ++ 2 files changed, 9 insertions(+) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 22193390e..4df5aca39 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -303,6 +303,13 @@ func (inp *Inp) writeFooter(f *os.File) error { return err } + // Just trying to be able to check for bad elements. + // TODO: Does it work? + _, err = f.WriteString(fmt.Sprintf("*ELSET, ELSET=ECheck, GENERATE\n1, %d\n", inp.Mesh.feCount())) + if err != nil { + return err + } + // Write analysis _, err = f.WriteString("*STEP\n*STATIC\n") diff --git a/render/finiteelements/mesh/mesh.go b/render/finiteelements/mesh/mesh.go index 7bd0beaae..701b61cea 100644 --- a/render/finiteelements/mesh/mesh.go +++ b/render/finiteelements/mesh/mesh.go @@ -12,6 +12,8 @@ type FE interface { layerCount() int // Number of finite elements on a layer. feCountOnLayer(l int) int + // Total number of elements for all layers. + feCount() int // Get a finite element. // FE vertices are returned. // Layer index is input. From aeef667a1a8ce890e849add63dd443fad4402de6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 29 May 2023 15:40:45 +0330 Subject: [PATCH 444/775] New `Tet10` element --- examples/finite_elements/main.go | 22 +++++ render/finiteelements/mesh/tet10.go | 147 ++++++++++++++++++++++++++++ render/march3fe.go | 14 +++ render/march3fetet10.go | 119 ++++++++++++++++++++++ render/render.go | 31 ++++++ render/tet10.go | 44 +++++++++ 6 files changed, 377 insertions(+) create mode 100644 render/finiteelements/mesh/tet10.go create mode 100644 render/march3fetet10.go create mode 100644 render/tet10.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 5f2e6367c..b2190da43 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -36,6 +36,23 @@ func tet4(s sdf.SDF3, resolution int, pth string) error { return nil } +// 10-node tetrahedral elements. +func tet10(s sdf.SDF3, resolution int, pth string) error { + // Create a mesh out of finite elements. + m, _ := mesh.NewTet10(s, render.NewMarchingCubesFEUniform(resolution)) + + lyrStart := 0 + lyrEnd := 20 + + // Write just some layers of mesh to a file. + err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + if err != nil { + return err + } + + return nil +} + // 8-node hexahedral elements. func hex8(s sdf.SDF3, resolution int, pth string) error { // Create a mesh out of finite elements. @@ -124,6 +141,11 @@ func main() { log.Fatalf("error: %s", err) } + err = tet10(teapotSdf, 80, "teapot-tet10.inp") + if err != nil { + log.Fatalf("error: %s", err) + } + err = hex8(teapotSdf, 80, "teapot-hex8.inp") if err != nil { log.Fatalf("error: %s", err) diff --git a/render/finiteelements/mesh/tet10.go b/render/finiteelements/mesh/tet10.go new file mode 100644 index 000000000..fb8d8f787 --- /dev/null +++ b/render/finiteelements/mesh/tet10.go @@ -0,0 +1,147 @@ +package mesh + +import ( + "github.com/deadsy/sdfx/render" + "github.com/deadsy/sdfx/render/finiteelements/buffer" + "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// Tet10 is a mesh of 10-node tetrahedra. +// A sophisticated data structure for mesh is required. +// The repeated nodes would be removed. +// The element connectivity would be created with unique nodes. +type Tet10 struct { + // Index buffer. + IBuff *buffer.IB + // Vertex buffer. + VBuff *buffer.VB +} + +// NewTet10 returns a new mesh and number of its layers along Z-axis. +func NewTet10(s sdf.SDF3, r render.RenderFE) (*Tet10, int) { + fes := render.ToTet10(s, r) + + _, _, layerCountZ := r.LayerCounts(s) + + m := newTet10(layerCountZ) + + // Fill out the mesh with finite elements. + for _, fe := range fes { + nodes := [10]v3.Vec{} + for n := 0; n < 10; n++ { + nodes[n] = fe.V[n] + } + m.addFE(fe.Layer, nodes) + } + + defer m.VBuff.DestroyHashTable() + + return m, layerCountZ +} + +func newTet10(layerCount int) *Tet10 { + return &Tet10{ + IBuff: buffer.NewIB(layerCount, 10), + VBuff: buffer.NewVB(), + } +} + +// Npe returns number of nodes per element. +func (m *Tet10) Npe() int { + return 10 +} + +// Add a finite element to mesh. +// Layer number and nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (m *Tet10) addFE(l int, nodes [10]v3.Vec) { + indices := [10]uint32{} + for n := 0; n < 10; n++ { + indices[n] = m.addVertex(nodes[n]) + } + m.IBuff.AddFE(l, indices[:]) +} + +func (m *Tet10) addVertex(vert v3.Vec) uint32 { + return m.VBuff.Id(vert) +} + +func (m *Tet10) vertexCount() int { + return m.VBuff.VertexCount() +} + +func (m *Tet10) vertex(i uint32) v3.Vec { + return m.VBuff.Vertex(i) +} + +// Number of layers along the Z axis. +func (m *Tet10) layerCount() int { + return m.IBuff.LayerCount() +} + +// Number of finite elements on a layer. +func (m *Tet10) feCountOnLayer(l int) int { + return m.IBuff.FECountOnLayer(l) +} + +// Number of finite elements for all layers. +func (m *Tet10) feCount() int { + return m.IBuff.FECount() +} + +// Get a finite element. +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *Tet10) feIndicies(l, i int) []uint32 { + return m.IBuff.FEIndicies(l, i) +} + +// Get a finite element. +// Layer number is input. +// FE index on layer is input. +// FE index could be from 0 to number of tetrahedra on layer. +// Don't return error to increase performance. +func (m *Tet10) feVertices(l, i int) []v3.Vec { + indices := m.IBuff.FEIndicies(l, i) + vertices := make([]v3.Vec, 10) + for n := 0; n < 10; n++ { + vertices[n] = m.VBuff.Vertex(indices[n]) + } + return vertices +} + +// WriteInp saves mesh to ABAQUS or CalculiX `inp` file. +// Units of measurement are mm,N,s,K. +// Refer to https://engineering.stackexchange.com/q/54454/15178 +func (m *Tet10) WriteInp( + path string, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) +} + +// WriteInpLayers saves specific layers of mesh to ABAQUS or CalculiX `inp` file. +// Result would include start layer. +// Result would exclude end layer. +// Units of measurement are mm,N,s,K. +// Refer to https://engineering.stackexchange.com/q/54454/15178 +func (m *Tet10) WriteInpLayers( + path string, + layerStart, layerEnd int, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) + return inp.Write() +} + +//----------------------------------------------------------------------------- diff --git a/render/march3fe.go b/render/march3fe.go index af1e69760..f0c26bd72 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -60,6 +60,20 @@ func (r *MarchingCubesFEUniform) RenderTet4(s sdf.SDF3, output chan<- []*Tet4) { output <- marchingCubesTet4(s, bb, meshInc) } +// Render produces a finite elements mesh over the bounding volume of an sdf3. +// Finite elements are in the shape of tetrahedra. +func (r *MarchingCubesFEUniform) RenderTet10(s sdf.SDF3, output chan<- []*Tet10) { + // work out the region we will sample + bb0 := s.BoundingBox() + bb0Size := bb0.Size() + meshInc := bb0Size.MaxComponent() / float64(r.meshCells) + bb1Size := bb0Size.DivScalar(meshInc) + bb1Size = bb1Size.Ceil().AddScalar(1) + bb1Size = bb1Size.MulScalar(meshInc) + bb := sdf.NewBox3(bb0.Center(), bb1Size) + output <- marchingCubesTet10(s, bb, meshInc) +} + // Render produces a finite elements mesh over the bounding volume of an sdf3. // Finite elements are in the shape of hexahedra. func (r *MarchingCubesFEUniform) RenderHex8(s sdf.SDF3, output chan<- []*Hex8) { diff --git a/render/march3fetet10.go b/render/march3fetet10.go new file mode 100644 index 000000000..1ea4dc6d1 --- /dev/null +++ b/render/march3fetet10.go @@ -0,0 +1,119 @@ +package render + +import ( + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +//----------------------------------------------------------------------------- + +func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { + + var fes []*Tet10 + size := box.Size() + base := box.Min + steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) + inc := size.Div(conv.V3iToV3(steps)) + + // start the evaluation routines + evalRoutines() + + // create the SDF layer cache + l := newLayerYZ(base, inc, steps) + // evaluate the SDF for x = 0 + l.Evaluate(s, 0) + + nx, ny, nz := steps.X, steps.Y, steps.Z + dx, dy, dz := inc.X, inc.Y, inc.Z + + var p v3.Vec + p.X = base.X + for x := 0; x < nx; x++ { + // read the x + 1 layer + l.Evaluate(s, x+1) + // process all cubes in the x and x + 1 layers + p.Y = base.Y + for y := 0; y < ny; y++ { + p.Z = base.Z + for z := 0; z < nz; z++ { + x0, y0, z0 := p.X, p.Y, p.Z + x1, y1, z1 := x0+dx, y0+dy, z0+dz + corners := [8]v3.Vec{ + {x0, y0, z0}, + {x1, y0, z0}, + {x1, y1, z0}, + {x0, y1, z0}, + {x0, y0, z1}, + {x1, y0, z1}, + {x1, y1, z1}, + {x0, y1, z1}} + values := [8]float64{ + l.Get(0, y, z), + l.Get(1, y, z), + l.Get(1, y+1, z), + l.Get(0, y+1, z), + l.Get(0, y, z+1), + l.Get(1, y, z+1), + l.Get(1, y+1, z+1), + l.Get(0, y+1, z+1)} + fes = append(fes, mcToTet10(corners, values, 0, z)...) + p.Z += dz + } + p.Y += dy + } + p.X += dx + } + + return fes +} + +//----------------------------------------------------------------------------- + +func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { + // which of the 0..255 patterns do we have? + index := 0 + for i := 0; i < 8; i++ { + if v[i] < x { + index |= 1 << uint(i) + } + } + + // work out the interpolated points on the edges + var points [12]v3.Vec + for i := 0; i < 12; i++ { + bit := 1 << uint(i) + if mcEdgeTable[index]&bit != 0 { + a := mcPairTable[i][0] + b := mcPairTable[i][1] + points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) + } + } + + // Create the tetrahedra. + table := mcTetrahedronTable[index] + count := len(table) / 4 + result := make([]*Tet10, 0, count) + for i := 0; i < count; i++ { + t := Tet10{ + V: [10]v3.Vec{}, + Layer: layerZ, + } + // TODO: Fill out vertices correctly. + t.V[0] = point(points, p, table[i*4+0]) + t.V[1] = point(points, p, table[i*4+1]) + t.V[2] = point(points, p, table[i*4+2]) + t.V[3] = point(points, p, table[i*4+3]) + t.V[4] = v3.Vec{} + t.V[5] = v3.Vec{} + t.V[6] = v3.Vec{} + t.V[7] = v3.Vec{} + t.V[8] = v3.Vec{} + t.V[9] = v3.Vec{} + result = append(result, &t) + } + + return result +} + +//----------------------------------------------------------------------------- diff --git a/render/render.go b/render/render.go index 7811b33ab..a7bd7de69 100644 --- a/render/render.go +++ b/render/render.go @@ -32,6 +32,7 @@ type Render2 interface { // RenderFE renders a finite element mesh over the bounding volume of an sdf3. type RenderFE interface { RenderTet4(sdf3 sdf.SDF3, output chan<- []*Tet4) + RenderTet10(sdf3 sdf.SDF3, output chan<- []*Tet10) RenderHex8(sdf3 sdf.SDF3, output chan<- []*Hex8) RenderHex20(sdf3 sdf.SDF3, output chan<- []*Hex20) Info(sdf3 sdf.SDF3) string @@ -91,6 +92,36 @@ func ToTet4( //----------------------------------------------------------------------------- +// ToTet10 renders an SDF3 to finite elements in the shape of 10-node tetrahedra. +func ToTet10( + s sdf.SDF3, // sdf3 to render + r RenderFE, // rendering method +) []Tet10 { + fmt.Printf("rendering %s\n", r.Info(s)) + + layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) + fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) + + // Will be filled by the rendering. + fes := make([]Tet10, 0) + + var wg sync.WaitGroup + + // Get the channel to be written to. + output := writeTet10(&wg, &fes) + + // run the renderer + r.RenderTet10(s, output) + // stop the writer reading on the channel + close(output) + // wait for the file write to complete + wg.Wait() + + return fes +} + +//----------------------------------------------------------------------------- + // ToHex8 renders an SDF3 to finite elements in the shape of 8-node hexahedra. func ToHex8( s sdf.SDF3, // sdf3 to render diff --git a/render/tet10.go b/render/tet10.go new file mode 100644 index 000000000..e738b5315 --- /dev/null +++ b/render/tet10.go @@ -0,0 +1,44 @@ +package render + +import ( + "sync" + + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// Tet10 is a 3D tetrahedron consisting of 10 nodes. +// It's a kind of finite element, FE. +// https://en.wikipedia.org/wiki/Tetrahedron +type Tet10 struct { + // Coordinates of corner nodes or vertices. + V [10]v3.Vec + // The Layer to which tetrahedron belongs. Layers are along Z axis. + // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store Layer along Z axis. + // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. + // Sampling/marching algorithm is expected to return the Layer to which a finite element belongs. + Layer int +} + +//----------------------------------------------------------------------------- + +// writeTet10 writes a stream of finite elements to an array. +func writeTet10(wg *sync.WaitGroup, tet10s *[]Tet10) chan<- []*Tet10 { + // External code writes to this channel. + // This goroutine reads the channel and stores finite elements. + c := make(chan []*Tet10) + + wg.Add(1) + go func() { + defer wg.Done() + // read finite elements from the channel and handle them + for fes := range c { + for _, fe := range fes { + *tet10s = append(*tet10s, *fe) + } + } + }() + + return c +} + +//----------------------------------------------------------------------------- From f1cc7a4ed7716420f6b2257d4148b5381dbdf285 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 29 May 2023 15:48:42 +0330 Subject: [PATCH 445/775] Remove adaptive algorithm --- examples/finite_elements/main.go | 18 ----- render/march3xfe.go | 117 ------------------------------- render/march3xfehex20.go | 42 ----------- render/march3xfehex8.go | 72 ------------------- render/march3xfetet4.go | 42 ----------- 5 files changed, 291 deletions(-) delete mode 100644 render/march3xfe.go delete mode 100644 render/march3xfehex20.go delete mode 100644 render/march3xfehex8.go delete mode 100644 render/march3xfetet4.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index b2190da43..c48f6b12a 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -105,19 +105,6 @@ func hex20(s sdf.SDF3, resolution int, pth string) error { return nil } -// 8-node hexahedral elements. -// With adaptive mesh refinement. -func hex8adaptive(s sdf.SDF3, resolution int, pth string) error { - // Create a mesh out of finite elements. - m, _ := mesh.NewHex8(s, render.NewMarchingCubesFEOctree(resolution)) - - err := m.WriteInp(pth, []int{0}, 1.25e-9, 900, 0.3) - if err != nil { - return err - } - return nil -} - // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. @@ -155,9 +142,4 @@ func main() { if err != nil { log.Fatalf("error: %s", err) } - - err = hex8adaptive(teapotSdf, 80, "teapot-hex20-adaptive.inp") - if err != nil { - log.Fatalf("error: %s", err) - } } diff --git a/render/march3xfe.go b/render/march3xfe.go deleted file mode 100644 index 6dc9d5371..000000000 --- a/render/march3xfe.go +++ /dev/null @@ -1,117 +0,0 @@ -//----------------------------------------------------------------------------- -/* - -Marching Cubes Octree - -Convert an SDF3 to finite elements. -Uses octree space subdivision. - -*/ -//----------------------------------------------------------------------------- - -package render - -import ( - "fmt" - "math" - - "github.com/deadsy/sdfx/sdf" - "github.com/deadsy/sdfx/vec/conv" - "github.com/deadsy/sdfx/vec/v3i" -) - -//----------------------------------------------------------------------------- - -func distanceCache(s sdf.SDF3, resolution float64) (*dcache3, uint) { - // Scale the bounding box about the center to make sure the boundaries - // aren't on the object surface. - bb := s.BoundingBox() - bb = bb.ScaleAboutCenter(1.01) - longAxis := bb.Size().MaxComponent() - // We want to test the smallest cube (side == resolution) for emptiness - // so the level = 0 cube is at half resolution. - resolution = 0.5 * resolution - // how many cube levels for the octree? - levels := uint(math.Ceil(math.Log2(longAxis/resolution))) + 1 - // create the distance cache - dc := newDcache3(s, bb.Min, resolution, levels) - return dc, levels -} - -// marchingCubesTet4Octree generates finite elements for an SDF3 using octree subdivision. -func marchingCubesTet4Octree(s sdf.SDF3, resolution float64, output chan<- []*Tet4) { - dc, levels := distanceCache(s, resolution) - // process the octree, start at the top level - dc.processCubeTet4(&cube{v3i.Vec{0, 0, 0}, levels - 1}, output) -} - -// marchingCubesHex8Octree generates finite elements for an SDF3 using octree subdivision. -func marchingCubesHex8Octree(s sdf.SDF3, resolution float64, output chan<- []*Hex8) { - dc, levels := distanceCache(s, resolution) - // process the octree, start at the top level - dc.processCubeHex8(&cube{v3i.Vec{0, 0, 0}, levels - 1}, output) -} - -// marchingCubesHex20Octree generates finite elements for an SDF3 using octree subdivision. -func marchingCubesHex20Octree(s sdf.SDF3, resolution float64, output chan<- []*Hex20) { - dc, levels := distanceCache(s, resolution) - // process the octree, start at the top level - dc.processCubeHex20(&cube{v3i.Vec{0, 0, 0}, levels - 1}, output) -} - -//----------------------------------------------------------------------------- - -// MarchingCubesFEOctree renders using marching cubes with octree space sampling. -type MarchingCubesFEOctree struct { - meshCells int // number of cells on the longest axis of bounding box. e.g 200 -} - -// NewMarchingCubesFEOctree returns a Render3 object. -func NewMarchingCubesFEOctree(meshCells int) *MarchingCubesFEOctree { - return &MarchingCubesFEOctree{ - meshCells: meshCells, - } -} - -// Info returns a string describing the rendered volume. -func (r *MarchingCubesFEOctree) Info(s sdf.SDF3) string { - bbSize := s.BoundingBox().Size() - resolution := bbSize.MaxComponent() / float64(r.meshCells) - cells := conv.V3ToV3i(bbSize.MulScalar(1 / resolution)) - return fmt.Sprintf("%dx%dx%d, resolution %.2f", cells.X, cells.Y, cells.Z, resolution) -} - -// LayerCounts computes number of layes in X, Y, Z directions. -// We are specifically interested in Z direction. -func (r *MarchingCubesFEOctree) LayerCounts(s sdf.SDF3) (int, int, int) { - bbSize := s.BoundingBox().Size() - resolution := bbSize.MaxComponent() / float64(r.meshCells) - cells := conv.V3ToV3i(bbSize.MulScalar(1 / resolution)) - return cells.X, cells.Y, cells.Z -} - -// RenderTet4 produces finite elements over the bounding volume of an sdf3. -func (r *MarchingCubesFEOctree) RenderTet4(s sdf.SDF3, output chan<- []*Tet4) { - // work out the sampling resolution to use - bbSize := s.BoundingBox().Size() - resolution := bbSize.MaxComponent() / float64(r.meshCells) - marchingCubesTet4Octree(s, resolution, output) -} - -// RenderHex8 produces finite elements over the bounding volume of an sdf3. -func (r *MarchingCubesFEOctree) RenderHex8(s sdf.SDF3, output chan<- []*Hex8) { - // work out the sampling resolution to use - bbSize := s.BoundingBox().Size() - resolution := bbSize.MaxComponent() / float64(r.meshCells) - marchingCubesHex8Octree(s, resolution, output) -} - -// RenderHex20 produces finite elements over the bounding volume of an sdf3. -func (r *MarchingCubesFEOctree) RenderHex20(s sdf.SDF3, output chan<- []*Hex20) { - // work out the sampling resolution to use - bbSize := s.BoundingBox().Size() - resolution := bbSize.MaxComponent() / float64(r.meshCells) - marchingCubesHex20Octree(s, resolution, output) -} - -//----------------------------------------------------------------------------- diff --git a/render/march3xfehex20.go b/render/march3xfehex20.go deleted file mode 100644 index b88ae316b..000000000 --- a/render/march3xfehex20.go +++ /dev/null @@ -1,42 +0,0 @@ -package render - -import ( - v3 "github.com/deadsy/sdfx/vec/v3" - "github.com/deadsy/sdfx/vec/v3i" -) - -//----------------------------------------------------------------------------- - -// Process a cube. Generate finite elements, or more cubes. -func (dc *dcache3) processCubeHex20(c *cube, output chan<- []*Hex20) { - if !dc.isEmpty(c) { - if c.n == 1 { - // this cube is at the required resolution - c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) - c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) - c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) - c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) - c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) - c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) - c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) - c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) - corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} - values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} - // output the triangle(s) for this cube - output <- mcToHex20(corners, values, 0, -1) - } else { - // process the sub cubes - n := c.n - 1 - s := 1 << n - // TODO - turn these into throttled go-routines - dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{0, 0, 0}), n}, output) - dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{s, 0, 0}), n}, output) - dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{s, s, 0}), n}, output) - dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{0, s, 0}), n}, output) - dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{0, 0, s}), n}, output) - dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{s, 0, s}), n}, output) - dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{s, s, s}), n}, output) - dc.processCubeHex20(&cube{c.v.Add(v3i.Vec{0, s, s}), n}, output) - } - } -} diff --git a/render/march3xfehex8.go b/render/march3xfehex8.go deleted file mode 100644 index 209736295..000000000 --- a/render/march3xfehex8.go +++ /dev/null @@ -1,72 +0,0 @@ -package render - -import ( - v3 "github.com/deadsy/sdfx/vec/v3" - "github.com/deadsy/sdfx/vec/v3i" -) - -//----------------------------------------------------------------------------- - -// Process a cube. Generate finite elements, or more cubes. -func (dc *dcache3) processCubeHex8(c *cube, output chan<- []*Hex8) { - if !dc.isEmpty(c) { - - c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) - c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) - c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) - c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) - c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) - c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) - c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) - c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) - corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} - values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} - - anyPositive := false - for i := 0; i < 8; i++ { - if values[i] > 0 { - anyPositive = true - break - } - } - - if !anyPositive { - fe := Hex8{ - V: [8]v3.Vec{}, - Layer: 0, - } - - // Refer to CalculiX solver documentation: - // http://www.dhondt.de/ccx_2.20.pdf - - fe.V[7] = corners[7] - fe.V[6] = corners[6] - fe.V[5] = corners[5] - fe.V[4] = corners[4] - fe.V[3] = corners[3] - fe.V[2] = corners[2] - fe.V[1] = corners[1] - fe.V[0] = corners[0] - - // output the finite element(s) for this cube - output <- []*Hex8{&fe} - } - - if c.n == 1 { - // this cube is at the required resolution - } else { - // process the sub cubes - n := c.n - 1 - s := 1 << n - // TODO - turn these into throttled go-routines - dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{0, 0, 0}), n}, output) - dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{s, 0, 0}), n}, output) - dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{s, s, 0}), n}, output) - dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{0, s, 0}), n}, output) - dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{0, 0, s}), n}, output) - dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{s, 0, s}), n}, output) - dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{s, s, s}), n}, output) - dc.processCubeHex8(&cube{c.v.Add(v3i.Vec{0, s, s}), n}, output) - } - } -} diff --git a/render/march3xfetet4.go b/render/march3xfetet4.go deleted file mode 100644 index 876fd135f..000000000 --- a/render/march3xfetet4.go +++ /dev/null @@ -1,42 +0,0 @@ -package render - -import ( - v3 "github.com/deadsy/sdfx/vec/v3" - "github.com/deadsy/sdfx/vec/v3i" -) - -//----------------------------------------------------------------------------- - -// Process a cube. Generate finite elements, or more cubes. -func (dc *dcache3) processCubeTet4(c *cube, output chan<- []*Tet4) { - if !dc.isEmpty(c) { - if c.n == 1 { - // this cube is at the required resolution - c0, d0 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 0})) - c1, d1 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 0})) - c2, d2 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 0})) - c3, d3 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 0})) - c4, d4 := dc.evaluate(c.v.Add(v3i.Vec{0, 0, 2})) - c5, d5 := dc.evaluate(c.v.Add(v3i.Vec{2, 0, 2})) - c6, d6 := dc.evaluate(c.v.Add(v3i.Vec{2, 2, 2})) - c7, d7 := dc.evaluate(c.v.Add(v3i.Vec{0, 2, 2})) - corners := [8]v3.Vec{c0, c1, c2, c3, c4, c5, c6, c7} - values := [8]float64{d0, d1, d2, d3, d4, d5, d6, d7} - // output the triangle(s) for this cube - output <- mcToTet4(corners, values, 0, -1) - } else { - // process the sub cubes - n := c.n - 1 - s := 1 << n - // TODO - turn these into throttled go-routines - dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{0, 0, 0}), n}, output) - dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{s, 0, 0}), n}, output) - dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{s, s, 0}), n}, output) - dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{0, s, 0}), n}, output) - dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{0, 0, s}), n}, output) - dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{s, 0, s}), n}, output) - dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{s, s, s}), n}, output) - dc.processCubeTet4(&cube{c.v.Add(v3i.Vec{0, s, s}), n}, output) - } - } -} From 62265ffe9c08d7068fa4811f93ef965d03c28bfa Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 29 May 2023 16:05:03 +0330 Subject: [PATCH 446/775] Fix: writing `Tet10` elements to file --- render/finiteelements/mesh/inp.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 4df5aca39..9301acee4 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -105,6 +105,8 @@ func (inp *Inp) Write() error { ElementType := "" if inp.Mesh.Npe() == 4 { ElementType = "C3D4" + } else if inp.Mesh.Npe() == 10 { + ElementType = "C3D10" } else if inp.Mesh.Npe() == 8 { ElementType = "C3D8" } else if inp.Mesh.Npe() == 20 { @@ -226,6 +228,8 @@ func (inp *Inp) writeElements(f *os.File) error { if inp.Mesh.Npe() == 4 { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1)) + } else if inp.Mesh.Npe() == 10 { + _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1)) } else if inp.Mesh.Npe() == 8 { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) } else if inp.Mesh.Npe() == 20 { From 0864674332464cc0819e26ba719db23cc0753307 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 29 May 2023 16:21:32 +0330 Subject: [PATCH 447/775] Fill out `Tet10` points on tetrahedron edges --- render/march3fetet10.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 1ea4dc6d1..1f787ebe9 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -99,17 +99,19 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { V: [10]v3.Vec{}, Layer: layerZ, } - // TODO: Fill out vertices correctly. + // Points on tetrahedron corners. t.V[0] = point(points, p, table[i*4+0]) t.V[1] = point(points, p, table[i*4+1]) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) - t.V[4] = v3.Vec{} - t.V[5] = v3.Vec{} - t.V[6] = v3.Vec{} - t.V[7] = v3.Vec{} - t.V[8] = v3.Vec{} - t.V[9] = v3.Vec{} + // Points on tetrahedron edges. + // Followoing CalculiX node numbering. + t.V[5-1] = t.V[1-1].Add(t.V[2-1]).MulScalar(0.5) + t.V[6-1] = t.V[2-1].Add(t.V[3-1]).MulScalar(0.5) + t.V[7-1] = t.V[1-1].Add(t.V[3-1]).MulScalar(0.5) + t.V[8-1] = t.V[1-1].Add(t.V[4-1]).MulScalar(0.5) + t.V[9-1] = t.V[2-1].Add(t.V[4-1]).MulScalar(0.5) + t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) result = append(result, &t) } From 3b51b3ad51a013713b30feaed55ae80276a7240d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 31 May 2023 11:17:13 +0330 Subject: [PATCH 448/775] Fix case 100: a tetrahedron becomes too flat: CCX throws this error for it: *ERROR in e_c3d: nonpositive jacobian determinant in element 136 --- render/march3fetet4.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/render/march3fetet4.go b/render/march3fetet4.go index 4605a6671..e5585a574 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -933,13 +933,12 @@ var mcTetrahedronTable = [256][]int{ }, // 0b01100100 case 100 { - 1, 14, 2, 4, - 14, 2, 4, 6, - 1, 4, 9, 6, - 1, 14, 6, 9, - 14, 6, 9, 18, - 9, 18, 6, 4, - 4, 9, 18, 17, + 1, 14, 2, 6, + 1, 2, 4, 6, + 1, 14, 6, 18, + 1, 18, 6, 4, + 1, 18, 4, 9, + 9, 18, 4, 17, }, // 0b01100101 case 101 { From 039c9f64de71c708d2b9e0f0db5dbbc774b88287 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 31 May 2023 11:27:33 +0330 Subject: [PATCH 449/775] Low resolution to debug --- examples/finite_elements/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c48f6b12a..45db3a117 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -42,7 +42,7 @@ func tet10(s sdf.SDF3, resolution int, pth string) error { m, _ := mesh.NewTet10(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 - lyrEnd := 20 + lyrEnd := 5 // Write just some layers of mesh to a file. err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) @@ -128,7 +128,7 @@ func main() { log.Fatalf("error: %s", err) } - err = tet10(teapotSdf, 80, "teapot-tet10.inp") + err = tet10(teapotSdf, 10, "teapot-tet10.inp") if err != nil { log.Fatalf("error: %s", err) } From 78a82a08311d3ce2f45271b7fa07ac384e9cae0a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 31 May 2023 13:03:59 +0330 Subject: [PATCH 450/775] Generate elements along Z axis, in XY layers: So that the elements would be written to output file with the same order that they are generated. This way, we can easily place a break point when e.g. element number `136` on the output file is being generated. --- render/march3fe.go | 82 +++++++++++++++++++++++++++++++++++++++++ render/march3fetet10.go | 54 ++++++++++++++++----------- 2 files changed, 114 insertions(+), 22 deletions(-) diff --git a/render/march3fe.go b/render/march3fe.go index f0c26bd72..1c94e7e56 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -2,9 +2,12 @@ package render import ( "fmt" + "sync" "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" ) //----------------------------------------------------------------------------- @@ -103,3 +106,82 @@ func (r *MarchingCubesFEUniform) RenderHex20(s sdf.SDF3, output chan<- []*Hex20) } //----------------------------------------------------------------------------- + +type layerXY struct { + base v3.Vec // base coordinate of layer + inc v3.Vec // dx, dy, dz for each step + steps v3i.Vec // number of x,y,z steps + val0 []float64 // SDF values for z layer + val1 []float64 // SDF values for z + dz layer +} + +func newLayerXY(base, inc v3.Vec, steps v3i.Vec) *layerXY { + return &layerXY{base, inc, steps, nil, nil} +} + +// Evaluate the SDF for a given XY layer +func (l *layerXY) Evaluate(s sdf.SDF3, z int) { + + // Swap the layers + l.val0, l.val1 = l.val1, l.val0 + + nx, ny := l.steps.X, l.steps.Y + dx, dy, dz := l.inc.X, l.inc.Y, l.inc.Z + + // allocate storage + if l.val1 == nil { + l.val1 = make([]float64, (nx+1)*(ny+1)) + } + + // setup the loop variables + var p v3.Vec + p.Z = l.base.Z + float64(z)*dz + + // define the base struct for requesting evaluation + eReq := evalReq{ + wg: new(sync.WaitGroup), + fn: s.Evaluate, + out: l.val1, + } + + // evaluate the layer + p.X = l.base.X + + // Performance doesn't seem to improve past 100. + const batchSize = 100 + + eReq.p = make([]v3.Vec, 0, batchSize) + for x := 0; x < nx+1; x++ { + p.Y = l.base.Y + for y := 0; y < ny+1; y++ { + eReq.p = append(eReq.p, p) + if len(eReq.p) == batchSize { + eReq.wg.Add(1) + evalProcessCh <- eReq + eReq.out = eReq.out[batchSize:] // shift the output slice for processing + eReq.p = make([]v3.Vec, 0, batchSize) // create a new slice for the next batch + } + p.Y += dy + } + p.X += dx + } + + // send any remaining points for processing + if len(eReq.p) > 0 { + eReq.wg.Add(1) + evalProcessCh <- eReq + } + + // Wait for all processing to complete before returning + eReq.wg.Wait() +} + +func (l *layerXY) Get(x, y, z int) float64 { + idz := x*(l.steps.Y+1) + y + if z == 0 { + return l.val0[idz] + } + return l.val1[idz] +} + +//----------------------------------------------------------------------------- diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 1f787ebe9..0adf3ccae 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -1,6 +1,8 @@ package render import ( + "fmt" + "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" @@ -20,23 +22,23 @@ func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { evalRoutines() // create the SDF layer cache - l := newLayerYZ(base, inc, steps) - // evaluate the SDF for x = 0 + l := newLayerXY(base, inc, steps) + // evaluate the SDF for z = 0 l.Evaluate(s, 0) nx, ny, nz := steps.X, steps.Y, steps.Z dx, dy, dz := inc.X, inc.Y, inc.Z var p v3.Vec - p.X = base.X - for x := 0; x < nx; x++ { - // read the x + 1 layer - l.Evaluate(s, x+1) - // process all cubes in the x and x + 1 layers - p.Y = base.Y - for y := 0; y < ny; y++ { - p.Z = base.Z - for z := 0; z < nz; z++ { + p.Z = base.Z + for z := 0; z < nz; z++ { + // read the z + 1 layer + l.Evaluate(s, z+1) + // process all cubes in the z and z + 1 layers + p.X = base.X + for x := 0; x < nx; x++ { + p.Y = base.Y + for y := 0; y < ny; y++ { x0, y0, z0 := p.X, p.Y, p.Z x1, y1, z1 := x0+dx, y0+dy, z0+dz corners := [8]v3.Vec{ @@ -49,20 +51,21 @@ func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { {x1, y1, z1}, {x0, y1, z1}} values := [8]float64{ - l.Get(0, y, z), - l.Get(1, y, z), - l.Get(1, y+1, z), - l.Get(0, y+1, z), - l.Get(0, y, z+1), - l.Get(1, y, z+1), - l.Get(1, y+1, z+1), - l.Get(0, y+1, z+1)} + l.Get(x, y, 0), + l.Get(x+1, y, 0), + l.Get(x+1, y+1, 0), + l.Get(x, y+1, 0), + l.Get(x, y, 1), + l.Get(x+1, y, 1), + l.Get(x+1, y+1, 1), + l.Get(x, y+1, 1), + } fes = append(fes, mcToTet10(corners, values, 0, z)...) - p.Z += dz + p.Y += dy } - p.Y += dy + p.X += dx } - p.X += dx + p.Z += dz } return fes @@ -70,6 +73,8 @@ func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { //----------------------------------------------------------------------------- +var eleCount int + func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { // which of the 0..255 patterns do we have? index := 0 @@ -113,6 +118,11 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[9-1] = t.V[2-1].Add(t.V[4-1]).MulScalar(0.5) t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) result = append(result, &t) + + eleCount++ + if eleCount == 136 { + fmt.Println("Bad element.") + } } return result From 9dac901e7fa7d3a66dba46f2341f529eacd75936 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 31 May 2023 13:18:54 +0330 Subject: [PATCH 451/775] Move debug breakpoint to before function calls --- render/march3fetet10.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 0adf3ccae..e14f3948d 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -104,6 +104,12 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { V: [10]v3.Vec{}, Layer: layerZ, } + + eleCount++ + if eleCount == 587 { + fmt.Println("Bad element.") + } + // Points on tetrahedron corners. t.V[0] = point(points, p, table[i*4+0]) t.V[1] = point(points, p, table[i*4+1]) @@ -118,11 +124,6 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[9-1] = t.V[2-1].Add(t.V[4-1]).MulScalar(0.5) t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) result = append(result, &t) - - eleCount++ - if eleCount == 136 { - fmt.Println("Bad element.") - } } return result From 06e70ded97a482c40395468ce8a22ba6fc6cc6f3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 31 May 2023 18:11:44 +0330 Subject: [PATCH 452/775] Fix 3 cases using edges without any triangles --- render/march3fetet4.go | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/render/march3fetet4.go b/render/march3fetet4.go index e5585a574..885a4a70a 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -320,15 +320,13 @@ var mcTetrahedronTable = [256][]int{ }, // 0b00011101 case 29 { + 1, 14, 15, 10, + 15, 1, 10, 11, + 12, 1, 15, 11, 12, 0, 1, 4, - 3, 12, 1, 4, - 15, 3, 1, 4, - 15, 4, 1, 7, - 15, 7, 1, 11, - 15, 12, 4, 7, + 12, 1, 11, 4, + 12, 4, 11, 7, 12, 4, 7, 16, - 1, 14, 15, 11, - 1, 14, 11, 10, }, // 0b00011110 case 30 { @@ -729,14 +727,12 @@ var mcTetrahedronTable = [256][]int{ }, // 0b01001110 case 78 { - 0, 13, 1, 9, - 1, 3, 0, 9, - 1, 3, 9, 11, - 1, 15, 3, 11, - 1, 14, 15, 11, - 1, 14, 11, 9, - 9, 14, 11, 5, - 14, 11, 5, 6, + 0, 13, 14, 9, + 14, 15, 3, 11, + 14, 3, 0, 9, + 14, 11, 3, 6, + 14, 3, 9, 5, + 14, 6, 3, 5, 14, 6, 5, 18, }, // 0b01001111 case 79 @@ -1866,18 +1862,15 @@ var mcTetrahedronTable = [256][]int{ }, // 0b10111111 case 191 { - 0, 15, 12, 8, - 0, 14, 15, 8, - 0, 13, 14, 8, - 8, 14, 15, 16, - 14, 15, 16, 19, - 13, 14, 8, 16, + 13, 15, 12, 16, + 13, 14, 15, 16, 13, 14, 16, 17, + 14, 15, 16, 19, 14, 16, 17, 5, + 14, 19, 16, 6, + 14, 6, 16, 10, 14, 16, 5, 10, - 10, 16, 5, 6, - 14, 19, 16, 10, - 10, 19, 16, 6, + 10, 6, 16, 5, }, // 0b11000000 case 192 { From aa42d9b1959cfb102f859be6918254f75d9f4ba3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 31 May 2023 18:12:30 +0330 Subject: [PATCH 453/775] Low resolution test is fine. Test higher one. --- examples/finite_elements/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 45db3a117..c48f6b12a 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -42,7 +42,7 @@ func tet10(s sdf.SDF3, resolution int, pth string) error { m, _ := mesh.NewTet10(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 - lyrEnd := 5 + lyrEnd := 20 // Write just some layers of mesh to a file. err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) @@ -128,7 +128,7 @@ func main() { log.Fatalf("error: %s", err) } - err = tet10(teapotSdf, 10, "teapot-tet10.inp") + err = tet10(teapotSdf, 80, "teapot-tet10.inp") if err != nil { log.Fatalf("error: %s", err) } From 4bd7eae8aff535290e4a1337d84cf331795ddc93 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 12:42:16 +0330 Subject: [PATCH 454/775] Doublecheck zero-volume elements by marching cubes --- render/march3fe.go | 29 +++++++++++++++++++++++++++++ render/march3fetet10.go | 12 ++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/render/march3fe.go b/render/march3fe.go index 1c94e7e56..1f89661bc 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -185,3 +185,32 @@ func (l *layerXY) Get(x, y, z int) float64 { } //----------------------------------------------------------------------------- + +// MATHEMATICA script is available here: +// https://math.stackexchange.com/a/4709610/197913 +func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { + ab := b.Sub(a) + ac := c.Sub(a) + ad := d.Sub(a) + + // Note that the `Norm` function of MATHEMATICA is equivalent to our `Length()` function. + nab := ab.Length() + ncd := ac.Sub(ad).Length() + nbd := ab.Sub(ad).Length() + nbc := ab.Sub(ac).Length() + nac := ac.Length() + nad := ad.Length() + + volume := 1.0 / 6.0 * ab.Cross(ac).Dot(ad) + denom := (nab + ncd) * (nac + nbd) * (nad + nbc) + + // Tolerance derived from here: + // https://math.stackexchange.com/a/4709610/197913 + tolerance := 480.0 + + rho := tolerance * volume / denom + + return rho < 1, volume +} + +//----------------------------------------------------------------------------- diff --git a/render/march3fetet10.go b/render/march3fetet10.go index e14f3948d..d6e9804b0 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -106,7 +106,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { } eleCount++ - if eleCount == 587 { + if eleCount == 5641 { fmt.Println("Bad element.") } @@ -123,7 +123,15 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[8-1] = t.V[1-1].Add(t.V[4-1]).MulScalar(0.5) t.V[9-1] = t.V[2-1].Add(t.V[4-1]).MulScalar(0.5) t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) - result = append(result, &t) + // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. + // In our case of marching cubes algorithm to generate tetrahedron, we can avoid zero-volume elements by this check: + bad, volume := isZeroVolume(t.V[0], t.V[1], t.V[2], t.V[3]) + if !bad { + result = append(result, &t) + } else { + fmt.Printf("Bad element. Zero volume. Element number: %v, element volume: %v\n", eleCount, volume) + fmt.Printf("Bad element vertices: %v, %v, %v, %v\n", t.V[0], t.V[1], t.V[2], t.V[3]) + } } return result From d0d0e3e7e98747121841f2fe3e77cb56a3da0f89 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 13:06:24 +0330 Subject: [PATCH 455/775] Fix: volume needs absolute to be non-negative --- render/march3fe.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/render/march3fe.go b/render/march3fe.go index 1f89661bc..b142a4bf3 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -2,6 +2,7 @@ package render import ( "fmt" + "math" "sync" "github.com/deadsy/sdfx/sdf" @@ -201,7 +202,7 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { nac := ac.Length() nad := ad.Length() - volume := 1.0 / 6.0 * ab.Cross(ac).Dot(ad) + volume := 1.0 / 6.0 * math.Abs(ab.Cross(ac).Dot(ad)) denom := (nab + ncd) * (nac + nbd) * (nad + nbc) // Tolerance derived from here: From e269d9e2ed2b71425bf29375559b15f7d9b09431 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 13:18:38 +0330 Subject: [PATCH 456/775] Check for `0` edge lengths --- render/march3fe.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/render/march3fe.go b/render/march3fe.go index b142a4bf3..4a4a2bace 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -194,6 +194,13 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { ac := c.Sub(a) ad := d.Sub(a) + // Check for 0 edge lengths + if ab.Length() == 0 || ac.Sub(ad).Length() == 0 || + ab.Sub(ad).Length() == 0 || ab.Sub(ac).Length() == 0 || + ac.Length() == 0 || ad.Length() == 0 { + return true, 0 + } + // Note that the `Norm` function of MATHEMATICA is equivalent to our `Length()` function. nab := ab.Length() ncd := ac.Sub(ad).Length() From 13eca4c7e9303e9857d4e67e74abec8ae7573fa3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 13:25:30 +0330 Subject: [PATCH 457/775] Better check for `0` edge lengths --- render/march3fe.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/render/march3fe.go b/render/march3fe.go index 4a4a2bace..eab85b0f5 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -194,13 +194,6 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { ac := c.Sub(a) ad := d.Sub(a) - // Check for 0 edge lengths - if ab.Length() == 0 || ac.Sub(ad).Length() == 0 || - ab.Sub(ad).Length() == 0 || ab.Sub(ac).Length() == 0 || - ac.Length() == 0 || ad.Length() == 0 { - return true, 0 - } - // Note that the `Norm` function of MATHEMATICA is equivalent to our `Length()` function. nab := ab.Length() ncd := ac.Sub(ad).Length() @@ -209,6 +202,13 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { nac := ac.Length() nad := ad.Length() + // Check for 0 edge lengths + if nab == 0 || ncd == 0 || + nbd == 0 || nbc == 0 || + nac == 0 || nad == 0 { + return true, 0 + } + volume := 1.0 / 6.0 * math.Abs(ab.Cross(ac).Dot(ad)) denom := (nab + ncd) * (nac + nbd) * (nad + nbc) From 435d3258ddbeb8c00136b8ae20f2b051e4ddc2b0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 14:12:39 +0330 Subject: [PATCH 458/775] Simpler statements: vector subtraction --- render/march3fe.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/render/march3fe.go b/render/march3fe.go index eab85b0f5..57b19fe35 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -196,9 +196,9 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { // Note that the `Norm` function of MATHEMATICA is equivalent to our `Length()` function. nab := ab.Length() - ncd := ac.Sub(ad).Length() - nbd := ab.Sub(ad).Length() - nbc := ab.Sub(ac).Length() + ncd := d.Sub(c).Length() + nbd := d.Sub(b).Length() + nbc := c.Sub(b).Length() nac := ac.Length() nad := ad.Length() From 45a3eee6949852206fd73a7b80d4a46c9e603c70 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 14:23:57 +0330 Subject: [PATCH 459/775] Test with medium resolution --- examples/finite_elements/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c48f6b12a..a76ebb58c 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -42,7 +42,7 @@ func tet10(s sdf.SDF3, resolution int, pth string) error { m, _ := mesh.NewTet10(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 - lyrEnd := 20 + lyrEnd := 10 // Write just some layers of mesh to a file. err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) @@ -128,7 +128,7 @@ func main() { log.Fatalf("error: %s", err) } - err = tet10(teapotSdf, 80, "teapot-tet10.inp") + err = tet10(teapotSdf, 20, "teapot-tet10.inp") if err != nil { log.Fatalf("error: %s", err) } From f4cf46a06a9b4702e7435e5f2db812508c946caf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 14:25:53 +0330 Subject: [PATCH 460/775] Delete debug condition --- render/march3fetet10.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index d6e9804b0..c3434ded9 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -73,6 +73,7 @@ func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { //----------------------------------------------------------------------------- +// Just for debugging purposes. var eleCount int func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { @@ -105,10 +106,8 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { Layer: layerZ, } + // Just for debugging purposes. eleCount++ - if eleCount == 5641 { - fmt.Println("Bad element.") - } // Points on tetrahedron corners. t.V[0] = point(points, p, table[i*4+0]) From 457700f5cd7d9f33aa69a0163095814ecc55fad8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 14:29:20 +0330 Subject: [PATCH 461/775] Test with higher resolution --- examples/finite_elements/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index a76ebb58c..c48f6b12a 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -42,7 +42,7 @@ func tet10(s sdf.SDF3, resolution int, pth string) error { m, _ := mesh.NewTet10(s, render.NewMarchingCubesFEUniform(resolution)) lyrStart := 0 - lyrEnd := 10 + lyrEnd := 20 // Write just some layers of mesh to a file. err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) @@ -128,7 +128,7 @@ func main() { log.Fatalf("error: %s", err) } - err = tet10(teapotSdf, 20, "teapot-tet10.inp") + err = tet10(teapotSdf, 80, "teapot-tet10.inp") if err != nil { log.Fatalf("error: %s", err) } From bdd39e3743a16506fbfd01626b1a72912b7d8014 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 14:34:14 +0330 Subject: [PATCH 462/775] Delete debug log --- render/march3fetet10.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index c3434ded9..3522296f9 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -1,8 +1,6 @@ package render import ( - "fmt" - "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" @@ -124,12 +122,12 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can avoid zero-volume elements by this check: - bad, volume := isZeroVolume(t.V[0], t.V[1], t.V[2], t.V[3]) + bad, _ := isZeroVolume(t.V[0], t.V[1], t.V[2], t.V[3]) if !bad { result = append(result, &t) } else { - fmt.Printf("Bad element. Zero volume. Element number: %v, element volume: %v\n", eleCount, volume) - fmt.Printf("Bad element vertices: %v, %v, %v, %v\n", t.V[0], t.V[1], t.V[2], t.V[3]) + // fmt.Printf("Bad element. Zero volume. Element number: %v, element volume: %v\n", eleCount, volume) + // fmt.Printf("Bad element vertices: %v, %v, %v, %v\n", t.V[0], t.V[1], t.V[2], t.V[3]) } } From a86ab63b7a787e9326694177e29da8e17ddafa27 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 1 Jun 2023 17:10:36 +0330 Subject: [PATCH 463/775] Log bad element --- render/march3fetet10.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 3522296f9..6d2c89c03 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -1,6 +1,8 @@ package render import ( + "fmt" + "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" @@ -106,6 +108,9 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { // Just for debugging purposes. eleCount++ + if eleCount == 5781 { + fmt.Println("Bad element.") + } // Points on tetrahedron corners. t.V[0] = point(points, p, table[i*4+0]) From ada356b1192c4bbb82430f2d913c994c2581ddb9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 3 Jun 2023 17:22:34 +0330 Subject: [PATCH 464/775] Jacobian determinant doublecheck for Tet4 --- render/march3fe.go | 83 +++++++++++++++++++++++++++++++++++++++++ render/march3fetet10.go | 6 ++- render/march3fetet4.go | 20 +++++++++- 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/render/march3fe.go b/render/march3fe.go index 57b19fe35..2d112b95d 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -222,3 +222,86 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { } //----------------------------------------------------------------------------- + +// Check by four corner nodes of a 4-node or a 10-node tetrahedral element. +// A more complex method could be separately used for 10-node tetrahedral element. +// But let's keep things simple for now. +func isBad(a, b, c, d v3.Vec) (bool, float64) { + // Coordinates of the nodes. + var xl [3][4]float64 + + xl[0][0] = a.X + xl[1][0] = a.Y + xl[2][0] = a.Z + + xl[0][1] = b.X + xl[1][1] = b.Y + xl[2][1] = b.Z + + xl[0][2] = c.X + xl[1][2] = c.Y + xl[2][2] = c.Z + + xl[0][3] = d.X + xl[1][3] = d.Y + xl[2][3] = d.Z + + // xi, et, and ze are the coordinates of the Gauss point + // in the integration scheme for the 4-node tetrahedral element. + // For this element type, there is typically only 1 Gauss point used, + // which is located at the centroid of the tetrahedron. + // The coordinates of this Gauss point are (xi, et, ze) = (1/4, 1/4, 1/4). + var xi float64 = 0.25 + var et float64 = 0.25 + var ze float64 = 0.25 + + // Shape functions. + var shp [4][4]float64 + + shp[3][0] = 1.0 - xi - et - ze + shp[3][1] = xi + shp[3][2] = et + shp[3][3] = ze + + // local derivatives of the shape functions: xi-derivative + + shp[0][0] = -1.0 + shp[0][1] = 1.0 + shp[0][2] = 0.0 + shp[0][3] = 0.0 + + // local derivatives of the shape functions: eta-derivative + + shp[1][0] = -1.0 + shp[1][1] = 0.0 + shp[1][2] = 1.0 + shp[1][3] = 0.0 + + // local derivatives of the shape functions: zeta-derivative + + shp[2][0] = -1.0 + shp[2][1] = 0.0 + shp[2][2] = 0.0 + shp[2][3] = 1.0 + + // computation of the local derivative of the global coordinates (xs) + xs := [3][3]float64{} + for i := 0; i < 3; i++ { + for j := 0; j < 3; j++ { + xs[i][j] = 0.0 + for k := 0; k < 4; k++ { + xs[i][j] += xl[i][k] * shp[j][k] + } + } + } + + // computation of the jacobian determinant + xsj := xs[0][0]*(xs[1][1]*xs[2][2]-xs[1][2]*xs[2][1]) - + xs[0][1]*(xs[1][0]*xs[2][2]-xs[1][2]*xs[2][0]) + + xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) + + // According to CCX source code to detect nonpositive jacobian determinant in element + return xsj < 1e-20, xsj +} + +//----------------------------------------------------------------------------- diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 6d2c89c03..32d18291a 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -126,13 +126,15 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[9-1] = t.V[2-1].Add(t.V[4-1]).MulScalar(0.5) t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. - // In our case of marching cubes algorithm to generate tetrahedron, we can avoid zero-volume elements by this check: - bad, _ := isZeroVolume(t.V[0], t.V[1], t.V[2], t.V[3]) + // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: + bad, jacobianDeterminant := isBad(t.V[0], t.V[1], t.V[2], t.V[3]) if !bad { result = append(result, &t) } else { // fmt.Printf("Bad element. Zero volume. Element number: %v, element volume: %v\n", eleCount, volume) // fmt.Printf("Bad element vertices: %v, %v, %v, %v\n", t.V[0], t.V[1], t.V[2], t.V[3]) + fmt.Println("Bad element:", eleCount) + fmt.Println("Jacobian determinant:", jacobianDeterminant) } } diff --git a/render/march3fetet4.go b/render/march3fetet4.go index 885a4a70a..103a6277a 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -1,6 +1,8 @@ package render import ( + "fmt" + "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" @@ -99,11 +101,27 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { V: [4]v3.Vec{}, Layer: layerZ, } + + // Just for debugging purposes. + eleCount++ + if eleCount == 5781 { + fmt.Println("Bad element.") + } + t.V[0] = point(points, p, table[i*4+0]) t.V[1] = point(points, p, table[i*4+1]) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) - result = append(result, &t) + + // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. + // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: + bad, jacobianDeterminant := isBad(t.V[0], t.V[1], t.V[2], t.V[3]) + if !bad { + result = append(result, &t) + } else { + fmt.Println("Bad element:", eleCount) + fmt.Println("Jacobian determinant:", jacobianDeterminant) + } } return result From 60ef1964b7d2d973b5b00475c44141ef414859ed Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 3 Jun 2023 17:48:49 +0330 Subject: [PATCH 465/775] Prepare for a separate Tet10 double-check --- render/march3fe.go | 51 +++++++++++++++++++++-------------------- render/march3fetet10.go | 8 +++---- render/march3fetet4.go | 4 ++-- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/render/march3fe.go b/render/march3fe.go index 2d112b95d..5285f29fc 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -226,34 +226,15 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { // Check by four corner nodes of a 4-node or a 10-node tetrahedral element. // A more complex method could be separately used for 10-node tetrahedral element. // But let's keep things simple for now. -func isBad(a, b, c, d v3.Vec) (bool, float64) { +func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { // Coordinates of the nodes. var xl [3][4]float64 - xl[0][0] = a.X - xl[1][0] = a.Y - xl[2][0] = a.Z - - xl[0][1] = b.X - xl[1][1] = b.Y - xl[2][1] = b.Z - - xl[0][2] = c.X - xl[1][2] = c.Y - xl[2][2] = c.Z - - xl[0][3] = d.X - xl[1][3] = d.Y - xl[2][3] = d.Z - - // xi, et, and ze are the coordinates of the Gauss point - // in the integration scheme for the 4-node tetrahedral element. - // For this element type, there is typically only 1 Gauss point used, - // which is located at the centroid of the tetrahedron. - // The coordinates of this Gauss point are (xi, et, ze) = (1/4, 1/4, 1/4). - var xi float64 = 0.25 - var et float64 = 0.25 - var ze float64 = 0.25 + for i := 0; i < 4; i++ { + xl[0][i] = coords[i].X + xl[1][i] = coords[i].Y + xl[2][i] = coords[i].Z + } // Shape functions. var shp [4][4]float64 @@ -305,3 +286,23 @@ func isBad(a, b, c, d v3.Vec) (bool, float64) { } //----------------------------------------------------------------------------- + +func isBadTet4(coords [4]v3.Vec) (bool, float64) { + + // xi, et, and ze are the coordinates of the Gauss point + // in the integration scheme for the 4-node tetrahedral element. + // For this element type, there is typically only 1 Gauss point used, + // which is located at the centroid of the tetrahedron. + // The coordinates of this Gauss point are (xi, et, ze) = (1/4, 1/4, 1/4). + var xi float64 = 0.25 + var et float64 = 0.25 + var ze float64 = 0.25 + + return isBadGaussTet4(coords, xi, et, ze) +} + +func isBadTet10(a, b, c, d v3.Vec) bool { + return false +} + +//----------------------------------------------------------------------------- diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 32d18291a..0775e4f2f 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -127,14 +127,12 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, jacobianDeterminant := isBad(t.V[0], t.V[1], t.V[2], t.V[3]) + bad, volume := isZeroVolume(t.V[0], t.V[1], t.V[2], t.V[3]) if !bad { result = append(result, &t) } else { - // fmt.Printf("Bad element. Zero volume. Element number: %v, element volume: %v\n", eleCount, volume) - // fmt.Printf("Bad element vertices: %v, %v, %v, %v\n", t.V[0], t.V[1], t.V[2], t.V[3]) - fmt.Println("Bad element:", eleCount) - fmt.Println("Jacobian determinant:", jacobianDeterminant) + fmt.Println("Bad element: tet10:", eleCount) + fmt.Println("Volume:", volume) } } diff --git a/render/march3fetet4.go b/render/march3fetet4.go index 103a6277a..0ef8211bf 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -115,11 +115,11 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, jacobianDeterminant := isBad(t.V[0], t.V[1], t.V[2], t.V[3]) + bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) if !bad { result = append(result, &t) } else { - fmt.Println("Bad element:", eleCount) + fmt.Println("Bad element: tet4:", eleCount) fmt.Println("Jacobian determinant:", jacobianDeterminant) } } From 3ce3735dd76b0e4d87cd11db367e97080a7b9464 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 3 Jun 2023 18:10:56 +0330 Subject: [PATCH 466/775] Separate Tet4 and Tet4 doublechecks --- render/march3fe.go | 33 ++++++++++++++++++++++++++++----- render/march3fetet10.go | 12 ++++++------ render/march3fetet4.go | 5 ++++- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/render/march3fe.go b/render/march3fe.go index 5285f29fc..66b4b656c 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -223,9 +223,6 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { //----------------------------------------------------------------------------- -// Check by four corner nodes of a 4-node or a 10-node tetrahedral element. -// A more complex method could be separately used for 10-node tetrahedral element. -// But let's keep things simple for now. func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { // Coordinates of the nodes. var xl [3][4]float64 @@ -285,6 +282,10 @@ func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { return xsj < 1e-20, xsj } +func isBadGaussTet10(coords [10]v3.Vec, xi, et, ze float64) (bool, float64) { + return false, 0 +} + //----------------------------------------------------------------------------- func isBadTet4(coords [4]v3.Vec) (bool, float64) { @@ -301,8 +302,30 @@ func isBadTet4(coords [4]v3.Vec) (bool, float64) { return isBadGaussTet4(coords, xi, et, ze) } -func isBadTet10(a, b, c, d v3.Vec) bool { - return false +func isBadTet10(coords [10]v3.Vec) (bool, float64) { + // Gause points are according to CCX source code. + var gaussPoints [4]v3.Vec + gaussPoints[0] = v3.Vec{0.138196601125011, 0.138196601125011, 0.138196601125011} + gaussPoints[1] = v3.Vec{0.585410196624968, 0.138196601125011, 0.138196601125011} + gaussPoints[2] = v3.Vec{0.138196601125011, 0.585410196624968, 0.138196601125011} + gaussPoints[3] = v3.Vec{0.138196601125011, 0.138196601125011, 0.585410196624968} + + var bad bool + var jacobianDeterminant float64 + + for i := 0; i < 4; i++ { + bad, jacobianDeterminant = isBadGaussTet10(coords, gaussPoints[i].X, gaussPoints[i].Y, gaussPoints[i].Z) + if bad { + return true, jacobianDeterminant + } + } + + return false, jacobianDeterminant } //----------------------------------------------------------------------------- + +// Just for debugging purposes. +var eleCount int + +//----------------------------------------------------------------------------- diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 0775e4f2f..2cdb1f09c 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -11,6 +11,9 @@ import ( //----------------------------------------------------------------------------- func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { + // Just for debugging purposes. + // Reset element count. + eleCount = 0 var fes []*Tet10 size := box.Size() @@ -73,9 +76,6 @@ func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { //----------------------------------------------------------------------------- -// Just for debugging purposes. -var eleCount int - func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { // which of the 0..255 patterns do we have? index := 0 @@ -109,7 +109,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { // Just for debugging purposes. eleCount++ if eleCount == 5781 { - fmt.Println("Bad element.") + fmt.Println("Debug element.") } // Points on tetrahedron corners. @@ -127,12 +127,12 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, volume := isZeroVolume(t.V[0], t.V[1], t.V[2], t.V[3]) + bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) if !bad { result = append(result, &t) } else { fmt.Println("Bad element: tet10:", eleCount) - fmt.Println("Volume:", volume) + fmt.Println("Jacobian determinant:", jacobianDeterminant) } } diff --git a/render/march3fetet4.go b/render/march3fetet4.go index 0ef8211bf..98b3e1d3f 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -11,6 +11,9 @@ import ( //----------------------------------------------------------------------------- func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { + // Just for debugging purposes. + // Reset element count. + eleCount = 0 var fes []*Tet4 size := box.Size() @@ -105,7 +108,7 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // Just for debugging purposes. eleCount++ if eleCount == 5781 { - fmt.Println("Bad element.") + fmt.Println("Debug element.") } t.V[0] = point(points, p, table[i*4+0]) From 3da5bc382e88389e564234e404b1a64f1aeeb758 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 15:53:40 +0330 Subject: [PATCH 467/775] Tet10 double-check of Gauss points --- render/march3fe.go | 80 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/render/march3fe.go b/render/march3fe.go index 66b4b656c..1048c1711 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -283,7 +283,85 @@ func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { } func isBadGaussTet10(coords [10]v3.Vec, xi, et, ze float64) (bool, float64) { - return false, 0 + // Coordinates of the nodes. + var xl [3][10]float64 + + for i := 0; i < 10; i++ { + xl[0][i] = coords[i].X + xl[1][i] = coords[i].Y + xl[2][i] = coords[i].Z + } + + // Shape functions. + var shp [4][10]float64 + + // Shape functions + a := 1.0 - xi - et - ze + shp[3][0] = (2.0*a - 1.0) * a + shp[3][1] = xi * (2.0*xi - 1.0) + shp[3][2] = et * (2.0*et - 1.0) + shp[3][3] = ze * (2.0*ze - 1.0) + shp[3][4] = 4.0 * xi * a + shp[3][5] = 4.0 * xi * et + shp[3][6] = 4.0 * et * a + shp[3][7] = 4.0 * ze * a + shp[3][8] = 4.0 * xi * ze + shp[3][9] = 4.0 * et * ze + + // Local derivatives of the shape functions: xi-derivative + shp[0][0] = 1.0 - 4.0*a + shp[0][1] = 4.0*xi - 1.0 + shp[0][2] = 0.0 + shp[0][3] = 0.0 + shp[0][4] = 4.0 * (a - xi) + shp[0][5] = 4.0 * et + shp[0][6] = -4.0 * et + shp[0][7] = -4.0 * ze + shp[0][8] = 4.0 * ze + shp[0][9] = 0.0 + + // Local derivatives of the shape functions: eta-derivative + shp[1][0] = 1.0 - 4.0*a + shp[1][1] = 0.0 + shp[1][2] = 4.0*et - 1.0 + shp[1][3] = 0.0 + shp[1][4] = -4.0 * xi + shp[1][5] = 4.0 * xi + shp[1][6] = 4.0 * (a - et) + shp[1][7] = -4.0 * ze + shp[1][8] = 0.0 + shp[1][9] = 4.0 * ze + + // Local derivatives of the shape functions: zeta-derivative + shp[2][0] = 1.0 - 4.0*a + shp[2][1] = 0.0 + shp[2][2] = 0.0 + shp[2][3] = 4.0*ze - 1.0 + shp[2][4] = -4.0 * xi + shp[2][5] = 0.0 + shp[2][6] = -4.0 * et + shp[2][7] = 4.0 * (a - ze) + shp[2][8] = 4.0 * xi + shp[2][9] = 4.0 * et + + // Computation of the local derivative of the global coordinates (xs) + var xs [3][3]float64 + for i := 0; i < 3; i++ { + for j := 0; j < 3; j++ { + xs[i][j] = 0.0 + for k := 0; k < 10; k++ { + xs[i][j] = xs[i][j] + xl[i][k]*shp[j][k] + } + } + } + + // computation of the jacobian determinant + xsj := xs[0][0]*(xs[1][1]*xs[2][2]-xs[1][2]*xs[2][1]) - + xs[0][1]*(xs[1][0]*xs[2][2]-xs[1][2]*xs[2][0]) + + xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) + + // According to CCX source code to detect nonpositive jacobian determinant in element + return xsj < 1e-20, xsj } //----------------------------------------------------------------------------- From 3c3d7672a1a02a84128f8cada3ad307c579bdcb8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 16:02:29 +0330 Subject: [PATCH 468/775] Comment --- render/march3fe.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/render/march3fe.go b/render/march3fe.go index 1048c1711..b2b0cbe2b 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -223,6 +223,9 @@ func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { //----------------------------------------------------------------------------- +// Reference: +// CCX source code: +// ccx_2.20/src/shape4tet.f func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { // Coordinates of the nodes. var xl [3][4]float64 @@ -282,6 +285,9 @@ func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { return xsj < 1e-20, xsj } +// Reference: +// CCX source code: +// ccx_2.20/src/shape10tet.f func isBadGaussTet10(coords [10]v3.Vec, xi, et, ze float64) (bool, float64) { // Coordinates of the nodes. var xl [3][10]float64 From 781f450a0163238eb161a5cc5a884c5a7c657fef Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 16:04:09 +0330 Subject: [PATCH 469/775] Comment --- render/march3fe.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/render/march3fe.go b/render/march3fe.go index b2b0cbe2b..3da9e8335 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -379,6 +379,8 @@ func isBadTet4(coords [4]v3.Vec) (bool, float64) { // For this element type, there is typically only 1 Gauss point used, // which is located at the centroid of the tetrahedron. // The coordinates of this Gauss point are (xi, et, ze) = (1/4, 1/4, 1/4). + // Reference: + // ccx_2.20/src/gauss.f var xi float64 = 0.25 var et float64 = 0.25 var ze float64 = 0.25 @@ -388,6 +390,8 @@ func isBadTet4(coords [4]v3.Vec) (bool, float64) { func isBadTet10(coords [10]v3.Vec) (bool, float64) { // Gause points are according to CCX source code. + // Reference: + // ccx_2.20/src/gauss.f var gaussPoints [4]v3.Vec gaussPoints[0] = v3.Vec{0.138196601125011, 0.138196601125011, 0.138196601125011} gaussPoints[1] = v3.Vec{0.585410196624968, 0.138196601125011, 0.138196601125011} From dadce3d154bfa46d562c28b6cc40683e1e95b2ba Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 16:42:24 +0330 Subject: [PATCH 470/775] Comment --- render/march3fe.go | 10 ++++++++++ render/march3fetet4.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/render/march3fe.go b/render/march3fe.go index 3da9e8335..3a4b9dd5d 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -282,6 +282,11 @@ func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) // According to CCX source code to detect nonpositive jacobian determinant in element + // + // Fortran threshold for non-positive Jacobian determinant is 1e-20. + // But, for example a bad element with non-positive Jacobian determinant + // of 0.0025717779019105687 is escaping the 1e-20 threshold. + // Seems like we need to make the threshold safer. return xsj < 1e-20, xsj } @@ -367,6 +372,11 @@ func isBadGaussTet10(coords [10]v3.Vec, xi, et, ze float64) (bool, float64) { xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) // According to CCX source code to detect nonpositive jacobian determinant in element + // + // Fortran threshold for non-positive Jacobian determinant is 1e-20. + // But, for example a bad element with non-positive Jacobian determinant + // of 0.0025717779019105687 is escaping the 1e-20 threshold. + // Seems like we need to make the threshold safer. return xsj < 1e-20, xsj } diff --git a/render/march3fetet4.go b/render/march3fetet4.go index 98b3e1d3f..773777723 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -107,7 +107,7 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // Just for debugging purposes. eleCount++ - if eleCount == 5781 { + if eleCount == 40535 { fmt.Println("Debug element.") } From d5aed086d4ef7898d80e6050864405041d30dfb3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 18:12:00 +0330 Subject: [PATCH 471/775] Degenerate triangles --- render/march3fe.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/render/march3fe.go b/render/march3fe.go index 3a4b9dd5d..a2503de14 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -423,6 +423,31 @@ func isBadTet10(coords [10]v3.Vec) (bool, float64) { //----------------------------------------------------------------------------- +// If triangles are degenerate, then tetrahedra will be bad. +// TODO: Can this be used to filter bad tetrahedra? +func degenerateTriangles(index int, points [12]v3.Vec) bool { + // create the triangles + table := mcTriangleTable[index] + if len(table) < 1 { + // There are no triangles. + return false + } + count := len(table) / 3 + for i := 0; i < count; i++ { + t := Triangle3{} + t.V[2] = points[table[i*3+0]] + t.V[1] = points[table[i*3+1]] + t.V[0] = points[table[i*3+2]] + // Use the epsilon value of `vertexbuffer.go` + if t.Degenerate(0.0001) { + return true + } + } + return false +} + +//----------------------------------------------------------------------------- + // Just for debugging purposes. var eleCount int From cf34ec9f35df687bc7eca171083e65469dcc8e1b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 18:25:32 +0330 Subject: [PATCH 472/775] Tetrahedron sides could be degenerated: check them --- render/march3fe.go | 47 +++++++++++++++++++++++++---------------- render/march3fetet10.go | 3 ++- render/march3fetet4.go | 3 ++- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/render/march3fe.go b/render/march3fe.go index a2503de14..87d2cc51f 100644 --- a/render/march3fe.go +++ b/render/march3fe.go @@ -424,26 +424,37 @@ func isBadTet10(coords [10]v3.Vec) (bool, float64) { //----------------------------------------------------------------------------- // If triangles are degenerate, then tetrahedra will be bad. -// TODO: Can this be used to filter bad tetrahedra? -func degenerateTriangles(index int, points [12]v3.Vec) bool { - // create the triangles - table := mcTriangleTable[index] - if len(table) < 1 { - // There are no triangles. - return false +// To filter bad tetrahedra. +func degenerateTriangles(a, b, c, d v3.Vec) bool { + // 4 triangles are possible. + // Each triangle is a tetrahedron side. + t := Triangle3{} + t.V[0] = a + t.V[1] = b + t.V[2] = c + // Use the epsilon value of `vertexbuffer.go` + if t.Degenerate(0.0001) { + return true } - count := len(table) / 3 - for i := 0; i < count; i++ { - t := Triangle3{} - t.V[2] = points[table[i*3+0]] - t.V[1] = points[table[i*3+1]] - t.V[0] = points[table[i*3+2]] - // Use the epsilon value of `vertexbuffer.go` - if t.Degenerate(0.0001) { - return true - } + t.V[0] = a + t.V[1] = b + t.V[2] = d + // Use the epsilon value of `vertexbuffer.go` + if t.Degenerate(0.0001) { + return true + } + t.V[0] = a + t.V[1] = c + t.V[2] = d + // Use the epsilon value of `vertexbuffer.go` + if t.Degenerate(0.0001) { + return true } - return false + t.V[0] = b + t.V[1] = c + t.V[2] = d + // Use the epsilon value of `vertexbuffer.go` + return t.Degenerate(0.0001) } //----------------------------------------------------------------------------- diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 2cdb1f09c..6a16c543e 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -117,6 +117,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[1] = point(points, p, table[i*4+1]) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) + degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) // Points on tetrahedron edges. // Followoing CalculiX node numbering. t.V[5-1] = t.V[1-1].Add(t.V[2-1]).MulScalar(0.5) @@ -128,7 +129,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) - if !bad { + if !degenerated && !bad { result = append(result, &t) } else { fmt.Println("Bad element: tet10:", eleCount) diff --git a/render/march3fetet4.go b/render/march3fetet4.go index 773777723..75a7c3c22 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -115,11 +115,12 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { t.V[1] = point(points, p, table[i*4+1]) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) + degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) - if !bad { + if !degenerated && !bad { result = append(result, &t) } else { fmt.Println("Bad element: tet4:", eleCount) From 6972a1d5492f922814fc26e6c85c99d66ea8332f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 18:28:57 +0330 Subject: [PATCH 473/775] Delete extra log --- render/march3fetet10.go | 3 +-- render/march3fetet4.go | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 6a16c543e..28ba32795 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -128,12 +128,11 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) + bad, _ := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) if !degenerated && !bad { result = append(result, &t) } else { fmt.Println("Bad element: tet10:", eleCount) - fmt.Println("Jacobian determinant:", jacobianDeterminant) } } diff --git a/render/march3fetet4.go b/render/march3fetet4.go index 75a7c3c22..cd4b2b7cb 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -119,12 +119,11 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) + bad, _ := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) if !degenerated && !bad { result = append(result, &t) } else { fmt.Println("Bad element: tet4:", eleCount) - fmt.Println("Jacobian determinant:", jacobianDeterminant) } } From c797bfc78ca982305914228a454f46ea48a5e74c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 18:34:04 +0330 Subject: [PATCH 474/775] Debug a bad tetrahedron: Its Jacobian determinant is `0.01` --- render/march3fetet10.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 28ba32795..ad2848b5b 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -108,7 +108,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { // Just for debugging purposes. eleCount++ - if eleCount == 5781 { + if eleCount == 207589 { fmt.Println("Debug element.") } From 30be301cc546fe28361aa143050cdb65b01d60d7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 6 Jun 2023 18:49:10 +0330 Subject: [PATCH 475/775] Debug log again... --- render/march3fetet10.go | 3 ++- render/march3fetet4.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index ad2848b5b..0b688d2b9 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -128,11 +128,12 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, _ := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) + bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) if !degenerated && !bad { result = append(result, &t) } else { fmt.Println("Bad element: tet10:", eleCount) + fmt.Println("Jacobian determinant:", jacobianDeterminant) } } diff --git a/render/march3fetet4.go b/render/march3fetet4.go index cd4b2b7cb..75a7c3c22 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -119,11 +119,12 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, _ := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) + bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) if !degenerated && !bad { result = append(result, &t) } else { fmt.Println("Bad element: tet4:", eleCount) + fmt.Println("Jacobian determinant:", jacobianDeterminant) } } From a72694977e4e0ca8389c03adf1b007222bec7b4a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 09:45:02 +0330 Subject: [PATCH 476/775] Fix element count for debugging --- render/march3fetet10.go | 15 ++++++++------- render/march3fetet4.go | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/render/march3fetet10.go b/render/march3fetet10.go index 0b688d2b9..bd17bd665 100644 --- a/render/march3fetet10.go +++ b/render/march3fetet10.go @@ -106,12 +106,6 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { Layer: layerZ, } - // Just for debugging purposes. - eleCount++ - if eleCount == 207589 { - fmt.Println("Debug element.") - } - // Points on tetrahedron corners. t.V[0] = point(points, p, table[i*4+0]) t.V[1] = point(points, p, table[i*4+1]) @@ -131,8 +125,15 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) if !degenerated && !bad { result = append(result, &t) + + // Just for debugging purposes. + eleCount++ + if eleCount == 207589 { + fmt.Println("Debug element.") + } + } else { - fmt.Println("Bad element: tet10:", eleCount) + fmt.Println("Bad element: tet10: last good element was: ", eleCount) fmt.Println("Jacobian determinant:", jacobianDeterminant) } } diff --git a/render/march3fetet4.go b/render/march3fetet4.go index 75a7c3c22..16bcc961d 100644 --- a/render/march3fetet4.go +++ b/render/march3fetet4.go @@ -105,12 +105,6 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { Layer: layerZ, } - // Just for debugging purposes. - eleCount++ - if eleCount == 40535 { - fmt.Println("Debug element.") - } - t.V[0] = point(points, p, table[i*4+0]) t.V[1] = point(points, p, table[i*4+1]) t.V[2] = point(points, p, table[i*4+2]) @@ -122,8 +116,15 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) if !degenerated && !bad { result = append(result, &t) + + // Just for debugging purposes. + eleCount++ + if eleCount == 40535 { + fmt.Println("Debug element.") + } + } else { - fmt.Println("Bad element: tet4:", eleCount) + fmt.Println("Bad element: tet4: last good element was: ", eleCount) fmt.Println("Jacobian determinant:", jacobianDeterminant) } } From 808da2c3bdec2e149d319d53f19a5700e19e87ad Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 10:10:41 +0330 Subject: [PATCH 477/775] Rename files: simpler --- render/{march3fehex20.go => march3hex20.go} | 0 render/{march3fehex8.go => march3hex8.go} | 0 render/{march3fetet10.go => march3tet10.go} | 0 render/{march3fetet4.go => march3tet4.go} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename render/{march3fehex20.go => march3hex20.go} (100%) rename render/{march3fehex8.go => march3hex8.go} (100%) rename render/{march3fetet10.go => march3tet10.go} (100%) rename render/{march3fetet4.go => march3tet4.go} (100%) diff --git a/render/march3fehex20.go b/render/march3hex20.go similarity index 100% rename from render/march3fehex20.go rename to render/march3hex20.go diff --git a/render/march3fehex8.go b/render/march3hex8.go similarity index 100% rename from render/march3fehex8.go rename to render/march3hex8.go diff --git a/render/march3fetet10.go b/render/march3tet10.go similarity index 100% rename from render/march3fetet10.go rename to render/march3tet10.go diff --git a/render/march3fetet4.go b/render/march3tet4.go similarity index 100% rename from render/march3fetet4.go rename to render/march3tet4.go From eb5e08ec5d013ffa933ec67f4cb531b4a605890f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 10:16:21 +0330 Subject: [PATCH 478/775] Rename files: simpler? --- render/{march3fe.go => marchfe.go} | 0 render/{march3hex20.go => marchhex20.go} | 0 render/{march3hex8.go => marchhex8.go} | 0 render/{march3tet10.go => marchtet10.go} | 0 render/{march3tet4.go => marchtet4.go} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename render/{march3fe.go => marchfe.go} (100%) rename render/{march3hex20.go => marchhex20.go} (100%) rename render/{march3hex8.go => marchhex8.go} (100%) rename render/{march3tet10.go => marchtet10.go} (100%) rename render/{march3tet4.go => marchtet4.go} (100%) diff --git a/render/march3fe.go b/render/marchfe.go similarity index 100% rename from render/march3fe.go rename to render/marchfe.go diff --git a/render/march3hex20.go b/render/marchhex20.go similarity index 100% rename from render/march3hex20.go rename to render/marchhex20.go diff --git a/render/march3hex8.go b/render/marchhex8.go similarity index 100% rename from render/march3hex8.go rename to render/marchhex8.go diff --git a/render/march3tet10.go b/render/marchtet10.go similarity index 100% rename from render/march3tet10.go rename to render/marchtet10.go diff --git a/render/march3tet4.go b/render/marchtet4.go similarity index 100% rename from render/march3tet4.go rename to render/marchtet4.go From 0adfba5d851fc163dc7bf22006a4f5177db69605 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 10:24:17 +0330 Subject: [PATCH 479/775] Rename func --- render/marchfe.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/marchfe.go b/render/marchfe.go index 87d2cc51f..afe50c93b 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -189,7 +189,7 @@ func (l *layerXY) Get(x, y, z int) float64 { // MATHEMATICA script is available here: // https://math.stackexchange.com/a/4709610/197913 -func isZeroVolume(a, b, c, d v3.Vec) (bool, float64) { +func almostFlat(a, b, c, d v3.Vec) (bool, float64) { ab := b.Sub(a) ac := c.Sub(a) ad := d.Sub(a) From e264b44092a91145e138933a6e75b62f4cd1893c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 10:30:12 +0330 Subject: [PATCH 480/775] Double-check: flat or not? Effectively removed some bad elements --- render/marchtet10.go | 5 ++++- render/marchtet4.go | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/render/marchtet10.go b/render/marchtet10.go index bd17bd665..a54ff1cde 100644 --- a/render/marchtet10.go +++ b/render/marchtet10.go @@ -112,6 +112,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) + flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // Points on tetrahedron edges. // Followoing CalculiX node numbering. t.V[5-1] = t.V[1-1].Add(t.V[2-1]).MulScalar(0.5) @@ -123,7 +124,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) - if !degenerated && !bad { + if !degenerated && !bad && !flat { result = append(result, &t) // Just for debugging purposes. @@ -135,6 +136,8 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { } else { fmt.Println("Bad element: tet10: last good element was: ", eleCount) fmt.Println("Jacobian determinant:", jacobianDeterminant) + fmt.Println("Volume: ", volume) + fmt.Println("Degenerated?", degenerated) } } diff --git a/render/marchtet4.go b/render/marchtet4.go index 16bcc961d..4e5a78e37 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -110,11 +110,12 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) + flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) - if !degenerated && !bad { + if !degenerated && !bad && !flat { result = append(result, &t) // Just for debugging purposes. @@ -126,6 +127,8 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { } else { fmt.Println("Bad element: tet4: last good element was: ", eleCount) fmt.Println("Jacobian determinant:", jacobianDeterminant) + fmt.Println("Volume: ", volume) + fmt.Println("Degenerated?", degenerated) } } From 46847828426f303d18e5dbf6f981086e4ef2ab3e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 10:46:52 +0330 Subject: [PATCH 481/775] More debug logs --- render/marchtet10.go | 2 ++ render/marchtet4.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/render/marchtet10.go b/render/marchtet10.go index a54ff1cde..8581b17a1 100644 --- a/render/marchtet10.go +++ b/render/marchtet10.go @@ -135,7 +135,9 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { } else { fmt.Println("Bad element: tet10: last good element was: ", eleCount) + fmt.Println("Non-positive Jacobian determinant?", bad) fmt.Println("Jacobian determinant:", jacobianDeterminant) + fmt.Println("Almost flat?", flat) fmt.Println("Volume: ", volume) fmt.Println("Degenerated?", degenerated) } diff --git a/render/marchtet4.go b/render/marchtet4.go index 4e5a78e37..f85c00983 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -126,7 +126,9 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { } else { fmt.Println("Bad element: tet4: last good element was: ", eleCount) + fmt.Println("Non-positive Jacobian determinant?", bad) fmt.Println("Jacobian determinant:", jacobianDeterminant) + fmt.Println("Almost flat?", flat) fmt.Println("Volume: ", volume) fmt.Println("Degenerated?", degenerated) } From 5a92879989adc3e9c39ea45668b5452f12ba1299 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 10:49:15 +0330 Subject: [PATCH 482/775] Debug bad element --- render/marchtet4.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index f85c00983..8989a76b7 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -120,7 +120,7 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // Just for debugging purposes. eleCount++ - if eleCount == 40535 { + if eleCount == 39028 { fmt.Println("Debug element.") } From 20c148543adb6c0ea9f41c2bc20aa6c248900e74 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 10:53:23 +0330 Subject: [PATCH 483/775] Format logs --- render/marchtet10.go | 8 ++++---- render/marchtet4.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/render/marchtet10.go b/render/marchtet10.go index 8581b17a1..678c0df62 100644 --- a/render/marchtet10.go +++ b/render/marchtet10.go @@ -135,11 +135,11 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { } else { fmt.Println("Bad element: tet10: last good element was: ", eleCount) - fmt.Println("Non-positive Jacobian determinant?", bad) - fmt.Println("Jacobian determinant:", jacobianDeterminant) - fmt.Println("Almost flat?", flat) + fmt.Println("Non-positive Jacobian determinant? ", bad) + fmt.Println("Jacobian determinant: ", jacobianDeterminant) + fmt.Println("Almost flat? ", flat) fmt.Println("Volume: ", volume) - fmt.Println("Degenerated?", degenerated) + fmt.Println("Degenerated? ", degenerated) } } diff --git a/render/marchtet4.go b/render/marchtet4.go index 8989a76b7..12a45a188 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -126,11 +126,11 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { } else { fmt.Println("Bad element: tet4: last good element was: ", eleCount) - fmt.Println("Non-positive Jacobian determinant?", bad) - fmt.Println("Jacobian determinant:", jacobianDeterminant) - fmt.Println("Almost flat?", flat) + fmt.Println("Non-positive Jacobian determinant? ", bad) + fmt.Println("Jacobian determinant: ", jacobianDeterminant) + fmt.Println("Almost flat? ", flat) fmt.Println("Volume: ", volume) - fmt.Println("Degenerated?", degenerated) + fmt.Println("Degenerated? ", degenerated) } } From 089fb936d09d5f5e19e6f6c6456cc6cbe057c518 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 10 Jun 2023 12:28:15 +0330 Subject: [PATCH 484/775] Debug all bad elements --- render/marchtet4.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/marchtet4.go b/render/marchtet4.go index 12a45a188..fd1e97749 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -120,7 +120,7 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // Just for debugging purposes. eleCount++ - if eleCount == 39028 { + if eleCount == 39028 || eleCount == 39261 || eleCount == 80983 || eleCount == 81013 || eleCount == 145748 { fmt.Println("Debug element.") } From 202810d14f066e41464291282f9ab14dfc483276 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 11 Jun 2023 12:14:25 +0330 Subject: [PATCH 485/775] Debug repeated index/node of tetrahedron --- render/finiteelements/buffer/indexbuffer.go | 18 ++++++++++++++++++ render/finiteelements/mesh/inp.go | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index ee6d94140..59e2477bc 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -1,5 +1,7 @@ package buffer +import "fmt" + // Index buffer for a mesh of finite elements. type IB struct { // Every NodesPerElement indices would correspond to a finite element. @@ -28,6 +30,19 @@ func NewIB(layerCount, nodesPerElement int) *IB { return &ib } +func hasRepeatedValues(slice []uint32) bool { + valueMap := make(map[uint32]bool) + + for _, value := range slice { + if valueMap[value] { + return true + } + valueMap[value] = true + } + + return false +} + // Add a finite element to buffer. // Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. @@ -40,6 +55,9 @@ func (ib *IB) AddFE(l int, nodes []uint32) { panic("bad sizes: nodes of finite element") } ib.I[l] = append(ib.I[l], nodes...) + if hasRepeatedValues(nodes) { + fmt.Println("Bad element?") + } } // Number of layers along the Z axis. diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 9301acee4..d4443d3e0 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -219,6 +219,10 @@ func (inp *Inp) writeElements(f *os.File) error { var eleID uint32 for l := inp.LayerStart; l < inp.LayerEnd; l++ { for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { + if eleID+1 == 39028 { + fmt.Println("Debug element.") + } + nodes = inp.Mesh.feVertices(l, i) for n := 0; n < inp.Mesh.Npe(); n++ { ids[n] = inp.TempVBuff.Id(nodes[n]) @@ -227,6 +231,9 @@ func (inp *Inp) writeElements(f *os.File) error { // ID starts from one not zero. if inp.Mesh.Npe() == 4 { + if eleID+1 == 39028 { + fmt.Println("Debug element.") + } _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1)) } else if inp.Mesh.Npe() == 10 { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1)) From 159ed48b46c1236aab150eec9b9ac6b9d1ae7cee Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 11 Jun 2023 12:14:36 +0330 Subject: [PATCH 486/775] Revert "Debug repeated index/node of tetrahedron" This reverts commit 202810d14f066e41464291282f9ab14dfc483276. --- render/finiteelements/buffer/indexbuffer.go | 18 ------------------ render/finiteelements/mesh/inp.go | 7 ------- 2 files changed, 25 deletions(-) diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index 59e2477bc..ee6d94140 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -1,7 +1,5 @@ package buffer -import "fmt" - // Index buffer for a mesh of finite elements. type IB struct { // Every NodesPerElement indices would correspond to a finite element. @@ -30,19 +28,6 @@ func NewIB(layerCount, nodesPerElement int) *IB { return &ib } -func hasRepeatedValues(slice []uint32) bool { - valueMap := make(map[uint32]bool) - - for _, value := range slice { - if valueMap[value] { - return true - } - valueMap[value] = true - } - - return false -} - // Add a finite element to buffer. // Layer number and nodes are input. // The node numbering should follow the convention of CalculiX. @@ -55,9 +40,6 @@ func (ib *IB) AddFE(l int, nodes []uint32) { panic("bad sizes: nodes of finite element") } ib.I[l] = append(ib.I[l], nodes...) - if hasRepeatedValues(nodes) { - fmt.Println("Bad element?") - } } // Number of layers along the Z axis. diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index d4443d3e0..9301acee4 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -219,10 +219,6 @@ func (inp *Inp) writeElements(f *os.File) error { var eleID uint32 for l := inp.LayerStart; l < inp.LayerEnd; l++ { for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { - if eleID+1 == 39028 { - fmt.Println("Debug element.") - } - nodes = inp.Mesh.feVertices(l, i) for n := 0; n < inp.Mesh.Npe(); n++ { ids[n] = inp.TempVBuff.Id(nodes[n]) @@ -231,9 +227,6 @@ func (inp *Inp) writeElements(f *os.File) error { // ID starts from one not zero. if inp.Mesh.Npe() == 4 { - if eleID+1 == 39028 { - fmt.Println("Debug element.") - } _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1)) } else if inp.Mesh.Npe() == 10 { _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1)) From c43175d75203f1400ec72b7ab6ddf5928055ae53 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 11 Jun 2023 12:17:02 +0330 Subject: [PATCH 487/775] Remove element count logs: Was it showing the element ID that was eventually written to file? Not sure. --- render/marchfe.go | 5 ----- render/marchtet10.go | 13 +------------ render/marchtet4.go | 13 +------------ 3 files changed, 2 insertions(+), 29 deletions(-) diff --git a/render/marchfe.go b/render/marchfe.go index afe50c93b..a1a910c9a 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -458,8 +458,3 @@ func degenerateTriangles(a, b, c, d v3.Vec) bool { } //----------------------------------------------------------------------------- - -// Just for debugging purposes. -var eleCount int - -//----------------------------------------------------------------------------- diff --git a/render/marchtet10.go b/render/marchtet10.go index 678c0df62..c6a3a84de 100644 --- a/render/marchtet10.go +++ b/render/marchtet10.go @@ -11,10 +11,6 @@ import ( //----------------------------------------------------------------------------- func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { - // Just for debugging purposes. - // Reset element count. - eleCount = 0 - var fes []*Tet10 size := box.Size() base := box.Min @@ -126,15 +122,8 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) if !degenerated && !bad && !flat { result = append(result, &t) - - // Just for debugging purposes. - eleCount++ - if eleCount == 207589 { - fmt.Println("Debug element.") - } - } else { - fmt.Println("Bad element: tet10: last good element was: ", eleCount) + fmt.Println("Bad element: tet10") fmt.Println("Non-positive Jacobian determinant? ", bad) fmt.Println("Jacobian determinant: ", jacobianDeterminant) fmt.Println("Almost flat? ", flat) diff --git a/render/marchtet4.go b/render/marchtet4.go index fd1e97749..5da52fbad 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -11,10 +11,6 @@ import ( //----------------------------------------------------------------------------- func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { - // Just for debugging purposes. - // Reset element count. - eleCount = 0 - var fes []*Tet4 size := box.Size() base := box.Min @@ -117,15 +113,8 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) if !degenerated && !bad && !flat { result = append(result, &t) - - // Just for debugging purposes. - eleCount++ - if eleCount == 39028 || eleCount == 39261 || eleCount == 80983 || eleCount == 81013 || eleCount == 145748 { - fmt.Println("Debug element.") - } - } else { - fmt.Println("Bad element: tet4: last good element was: ", eleCount) + fmt.Println("Bad element: tet4") fmt.Println("Non-positive Jacobian determinant? ", bad) fmt.Println("Jacobian determinant: ", jacobianDeterminant) fmt.Println("Almost flat? ", flat) From be371d4b3c14cb05546ccabfaccd35b8fc194be5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 11 Jun 2023 12:37:37 +0330 Subject: [PATCH 488/775] Fix bug: repeated tetrahedron nodes --- render/finiteelements/buffer/vertexbuffer.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/render/finiteelements/buffer/vertexbuffer.go b/render/finiteelements/buffer/vertexbuffer.go index b9f1461a9..84c36bfad 100644 --- a/render/finiteelements/buffer/vertexbuffer.go +++ b/render/finiteelements/buffer/vertexbuffer.go @@ -11,14 +11,14 @@ import ( // The same vertex buffer is used for 4-node tetrahedra, 8-node hexahedra, and others. type VB struct { // To store index of vertices. Repeated vertices would have the same index. - hashTable map[[3]int32]uint32 + hashTable map[[3]float64]uint32 // To store coordinates of vertices. V []v3.Vec } func NewVB() *VB { b := VB{ - hashTable: map[[3]int32]uint32{}, + hashTable: map[[3]float64]uint32{}, V: []v3.Vec{}, } @@ -29,9 +29,10 @@ func NewVB() *VB { // If vertex is already available on the buffer, its ID is just returned. // So, all vertices will be unique. Not repeated. func (b *VB) Id(v v3.Vec) uint32 { - // Deduplicate by removing small details and use of epsilon - epsilon := float64(0.0001) - key := [3]int32{int32((v.X + epsilon) * 1000), int32((v.Y + epsilon) * 1000), int32((v.Z + epsilon) * 1000)} + // Do NOT remove any small details. Small details matter. + // Removing small details would cause this bug: + // https://calculix.discourse.group/t/detect-bad-finite-elements-4-node-tetrahedral/1700/5?u=megidd + key := [3]float64{v.X, v.Y, v.Z} if vID, ok := b.hashTable[key]; ok { // Vertex already exists. It's repeated. return vID From 8b447d8a3d10d09f66a8eb3bff362146e368de49 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 11 Jun 2023 13:53:40 +0330 Subject: [PATCH 489/775] Fix: avoid repeating nodes on file --- render/finiteelements/mesh/inp.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 9301acee4..bade0d796 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -189,6 +189,7 @@ func (inp *Inp) writeNodes(f *os.File) error { var err error nodes := make([]v3.Vec, 0, inp.Mesh.Npe()) ids := make([]uint32, inp.Mesh.Npe()) + var nextNode uint32 = 1 // ID starts from one not zero. for l := inp.LayerStart; l < inp.LayerEnd; l++ { for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { // Get the node IDs. @@ -199,11 +200,16 @@ func (inp *Inp) writeNodes(f *os.File) error { // Write the node IDs. for n := 0; n < inp.Mesh.Npe(); n++ { - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) - if err != nil { - return err + // Only write node if it's not already written to file. + if ids[n]+1 == nextNode { + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) + if err != nil { + return err + } + nextNode++ } + } } } From e913a68ba156b0cd15b9a6d2f468d2284e06e1c9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 11 Jun 2023 15:52:55 +0330 Subject: [PATCH 490/775] Fix: not repeating nodes of boundary --- render/finiteelements/mesh/inp.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index bade0d796..d55b358ee 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -261,6 +261,7 @@ func (inp *Inp) writeBoundary(f *os.File) error { var err error nodes := make([]v3.Vec, 0, inp.Mesh.Npe()) ids := make([]uint32, inp.Mesh.Npe()) + var nextNode uint32 = 1 // ID starts from one not zero. for l := range inp.LayersFixed { for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { nodes = inp.Mesh.feVertices(l, i) @@ -270,10 +271,14 @@ func (inp *Inp) writeBoundary(f *os.File) error { // Write the node IDs. for n := 0; n < inp.Mesh.Npe(); n++ { - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) - if err != nil { - return err + // Only write node if it's not already written to file. + if ids[n]+1 == nextNode { + // ID starts from one not zero. + _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) + if err != nil { + return err + } + nextNode++ } } } From 973f6df1b3ca6ed0a2e87e1ccf12a0fd2fbe19c6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 11 Jun 2023 16:19:26 +0330 Subject: [PATCH 491/775] Remove extra INP statement --- render/finiteelements/mesh/inp.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index d55b358ee..f0b37c27d 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -318,13 +318,6 @@ func (inp *Inp) writeFooter(f *os.File) error { return err } - // Just trying to be able to check for bad elements. - // TODO: Does it work? - _, err = f.WriteString(fmt.Sprintf("*ELSET, ELSET=ECheck, GENERATE\n1, %d\n", inp.Mesh.feCount())) - if err != nil { - return err - } - // Write analysis _, err = f.WriteString("*STEP\n*STATIC\n") From 83a66ea33852525a02982557cdd1ade84462fe9c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:05:35 +0330 Subject: [PATCH 492/775] Voxel grid to store elements spatially --- render/finiteelements/buffer/voxel.go | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 render/finiteelements/buffer/voxel.go diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go new file mode 100644 index 000000000..4fdf2feb8 --- /dev/null +++ b/render/finiteelements/buffer/voxel.go @@ -0,0 +1,44 @@ +package buffer + +type Element struct { + Nodes []uint32 // Node indices +} + +func NewElement(nodes []uint32) *Element { + e := Element{ + Nodes: nodes, + } + return &e +} + +// Acts like a three-dimensional nested slice using +// a one-dimensional slice under the hood. +// To increase performance. +type VoxelGrid struct { + data [][]Element // Each voxel stores multiple elements. + xLen, yLen, zLen int // Voxels count in 3 directions. +} + +func NewVoxelGrid(x, y, z int) *VoxelGrid { + return &VoxelGrid{ + data: make([][]Element, x*y*z), + xLen: x, + yLen: y, + zLen: z, + } +} + +// To get all the elements inside a voxel. +func (vg *VoxelGrid) Get(x, y, z int) []Element { + return vg.data[x*vg.yLen*vg.zLen+y*vg.zLen+z] +} + +// To set all the elements inside a voxel at once. +func (vg *VoxelGrid) Set(x, y, z int, value []Element) { + vg.data[x*vg.yLen*vg.zLen+y*vg.zLen+z] = value +} + +// To append a single element to the elements inside a voxel. +func (vg *VoxelGrid) Append(x, y, z int, value Element) { + vg.data[x*vg.yLen*vg.zLen+y*vg.zLen+z] = append(vg.data[x*vg.yLen*vg.zLen+y*vg.zLen+z], value) +} From 342b976689aa32a0cf1df6b3411c4dec3d1abacf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:13:34 +0330 Subject: [PATCH 493/775] Rename var --- render/finiteelements/buffer/voxel.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 4fdf2feb8..6ad91f284 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -16,29 +16,29 @@ func NewElement(nodes []uint32) *Element { // To increase performance. type VoxelGrid struct { data [][]Element // Each voxel stores multiple elements. - xLen, yLen, zLen int // Voxels count in 3 directions. + lenX, lenY, lenZ int // Voxels count in 3 directions. } func NewVoxelGrid(x, y, z int) *VoxelGrid { return &VoxelGrid{ data: make([][]Element, x*y*z), - xLen: x, - yLen: y, - zLen: z, + lenX: x, + lenY: y, + lenZ: z, } } // To get all the elements inside a voxel. func (vg *VoxelGrid) Get(x, y, z int) []Element { - return vg.data[x*vg.yLen*vg.zLen+y*vg.zLen+z] + return vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] } // To set all the elements inside a voxel at once. func (vg *VoxelGrid) Set(x, y, z int, value []Element) { - vg.data[x*vg.yLen*vg.zLen+y*vg.zLen+z] = value + vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] = value } // To append a single element to the elements inside a voxel. func (vg *VoxelGrid) Append(x, y, z int, value Element) { - vg.data[x*vg.yLen*vg.zLen+y*vg.zLen+z] = append(vg.data[x*vg.yLen*vg.zLen+y*vg.zLen+z], value) + vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] = append(vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z], value) } From e61904fe8345cdd731f190709633cdce38d489f6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:22:18 +0330 Subject: [PATCH 494/775] Store elements in voxel grid by their pointer --- render/finiteelements/buffer/voxel.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 6ad91f284..201a6ebda 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -15,13 +15,13 @@ func NewElement(nodes []uint32) *Element { // a one-dimensional slice under the hood. // To increase performance. type VoxelGrid struct { - data [][]Element // Each voxel stores multiple elements. - lenX, lenY, lenZ int // Voxels count in 3 directions. + data [][]*Element // Each voxel stores multiple elements. + lenX, lenY, lenZ int // Voxels count in 3 directions. } func NewVoxelGrid(x, y, z int) *VoxelGrid { return &VoxelGrid{ - data: make([][]Element, x*y*z), + data: make([][]*Element, x*y*z), lenX: x, lenY: y, lenZ: z, @@ -29,16 +29,16 @@ func NewVoxelGrid(x, y, z int) *VoxelGrid { } // To get all the elements inside a voxel. -func (vg *VoxelGrid) Get(x, y, z int) []Element { +func (vg *VoxelGrid) Get(x, y, z int) []*Element { return vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] } // To set all the elements inside a voxel at once. -func (vg *VoxelGrid) Set(x, y, z int, value []Element) { +func (vg *VoxelGrid) Set(x, y, z int, value []*Element) { vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] = value } // To append a single element to the elements inside a voxel. -func (vg *VoxelGrid) Append(x, y, z int, value Element) { +func (vg *VoxelGrid) Append(x, y, z int, value *Element) { vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] = append(vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z], value) } From 14f9c0b853f5d22938e633ebc1c197c2c4ff2418 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:33:13 +0330 Subject: [PATCH 495/775] Convenient iteration method --- render/finiteelements/buffer/voxel.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 201a6ebda..dff400c15 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -42,3 +42,15 @@ func (vg *VoxelGrid) Set(x, y, z int, value []*Element) { func (vg *VoxelGrid) Append(x, y, z int, value *Element) { vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] = append(vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z], value) } + +// To iterate over all voxels and do stuff with them. +func (t *VoxelGrid) Iterate(f func(x, y, z int, value []*Element)) { + for z := 0; z < t.lenZ; z++ { + for y := 0; y < t.lenY; y++ { + for x := 0; x < t.lenX; x++ { + value := t.Get(x, y, z) + f(x, y, z, value) + } + } + } +} From a1020fba5fab1b4881d251da9d610228d5731839 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:34:59 +0330 Subject: [PATCH 496/775] Comment --- render/finiteelements/buffer/voxel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index dff400c15..0ee86d4cc 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -43,7 +43,7 @@ func (vg *VoxelGrid) Append(x, y, z int, value *Element) { vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] = append(vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z], value) } -// To iterate over all voxels and do stuff with them. +// To iterate over all voxels and get elements inside each voxel and do stuff with them. func (t *VoxelGrid) Iterate(f func(x, y, z int, value []*Element)) { for z := 0; z < t.lenZ; z++ { for y := 0; y < t.lenY; y++ { From f0c6a2956a9a87cb5d121485eb13e61e7a081e6e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:36:52 +0330 Subject: [PATCH 497/775] Simpler iteration method --- render/finiteelements/buffer/voxel.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 0ee86d4cc..4823a6aac 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -44,12 +44,12 @@ func (vg *VoxelGrid) Append(x, y, z int, value *Element) { } // To iterate over all voxels and get elements inside each voxel and do stuff with them. -func (t *VoxelGrid) Iterate(f func(x, y, z int, value []*Element)) { +func (t *VoxelGrid) Iterate(f func(value []*Element)) { for z := 0; z < t.lenZ; z++ { for y := 0; y < t.lenY; y++ { for x := 0; x < t.lenX; x++ { value := t.Get(x, y, z) - f(x, y, z, value) + f(value) } } } From 012721b2190a4d683ec9490c84bddbd456367bdb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:37:16 +0330 Subject: [PATCH 498/775] Voxel grid --- render/finiteelements/buffer/voxel.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 4823a6aac..deecf4be0 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -44,11 +44,11 @@ func (vg *VoxelGrid) Append(x, y, z int, value *Element) { } // To iterate over all voxels and get elements inside each voxel and do stuff with them. -func (t *VoxelGrid) Iterate(f func(value []*Element)) { - for z := 0; z < t.lenZ; z++ { - for y := 0; y < t.lenY; y++ { - for x := 0; x < t.lenX; x++ { - value := t.Get(x, y, z) +func (vg *VoxelGrid) Iterate(f func(value []*Element)) { + for z := 0; z < vg.lenZ; z++ { + for y := 0; y < vg.lenY; y++ { + for x := 0; x < vg.lenX; x++ { + value := vg.Get(x, y, z) f(value) } } From b6f1cfba143ca0f34c267346a7627c60bffcd10f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:38:30 +0330 Subject: [PATCH 499/775] Simpler method --- render/finiteelements/buffer/voxel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index deecf4be0..6d5fb8c33 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -44,7 +44,7 @@ func (vg *VoxelGrid) Append(x, y, z int, value *Element) { } // To iterate over all voxels and get elements inside each voxel and do stuff with them. -func (vg *VoxelGrid) Iterate(f func(value []*Element)) { +func (vg *VoxelGrid) Iterate(f func([]*Element)) { for z := 0; z < vg.lenZ; z++ { for y := 0; y < vg.lenY; y++ { for x := 0; x < vg.lenX; x++ { From 2b3855d1359ad8c362f911b87ae555412e24eb62 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 13 Jun 2023 09:58:49 +0330 Subject: [PATCH 500/775] Element type --- render/finiteelements/buffer/voxel.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 6d5fb8c33..57c909f16 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -4,6 +4,21 @@ type Element struct { Nodes []uint32 // Node indices } +func (e *Element) Type() string { + el := "" + count := len(e.Nodes) + if count == 4 { + el = "C3D4" + } else if count == 10 { + el = "C3D10" + } else if count == 8 { + el = "C3D8" + } else if count == 20 { + el = "C3D20R" + } + return el +} + func NewElement(nodes []uint32) *Element { e := Element{ Nodes: nodes, From ac39ae79e23e7663897aa22735c129e492910bd7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 11:08:04 +0330 Subject: [PATCH 501/775] Refactor. Generate hex & tet simultaneously --- examples/finite_elements/main.go | 104 +- render/fe.go | 41 + render/finiteelements/buffer/indexbuffer.go | 65 +- render/finiteelements/buffer/voxel.go | 41 +- render/finiteelements/mesh/fem.go | 106 + render/finiteelements/mesh/hex20.go | 147 -- render/finiteelements/mesh/hex8.go | 147 -- render/finiteelements/mesh/inp.go | 366 ++- render/finiteelements/mesh/mesh.go | 21 +- render/finiteelements/mesh/tet10.go | 147 -- render/finiteelements/mesh/tet4.go | 139 - render/hex20.go | 44 - render/hex8.go | 44 - render/marchfe.go | 2600 ++++++++++++++++++- render/marchhex20.go | 18 +- render/marchhex20tet10.go | 83 + render/marchhex8.go | 18 +- render/marchhex8tet4.go | 82 + render/marchtet10.go | 18 +- render/marchtet4.go | 2506 +----------------- render/render.go | 107 +- render/tet10.go | 44 - render/tet4.go | 44 - 23 files changed, 3222 insertions(+), 3710 deletions(-) create mode 100644 render/fe.go create mode 100644 render/finiteelements/mesh/fem.go delete mode 100644 render/finiteelements/mesh/hex20.go delete mode 100644 render/finiteelements/mesh/hex8.go delete mode 100644 render/finiteelements/mesh/tet10.go delete mode 100644 render/finiteelements/mesh/tet4.go delete mode 100644 render/hex20.go delete mode 100644 render/hex8.go create mode 100644 render/marchhex20tet10.go create mode 100644 render/marchhex8tet4.go delete mode 100644 render/tet10.go delete mode 100644 render/tet4.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c48f6b12a..c86f64454 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -19,89 +19,17 @@ import ( "github.com/deadsy/sdfx/sdf" ) -// 4-node tetrahedral elements. -func tet4(s sdf.SDF3, resolution int, pth string) error { +// Generate finite elements. +func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, layerStart, layerEnd int) error { // Create a mesh out of finite elements. - m, _ := mesh.NewTet4(s, render.NewMarchingCubesFEUniform(resolution)) - - lyrStart := 0 - lyrEnd := 20 - - // Write just some layers of mesh to a file. - err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) - if err != nil { - return err - } - - return nil -} - -// 10-node tetrahedral elements. -func tet10(s sdf.SDF3, resolution int, pth string) error { - // Create a mesh out of finite elements. - m, _ := mesh.NewTet10(s, render.NewMarchingCubesFEUniform(resolution)) - - lyrStart := 0 - lyrEnd := 20 - - // Write just some layers of mesh to a file. - err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) - if err != nil { - return err - } - - return nil -} - -// 8-node hexahedral elements. -func hex8(s sdf.SDF3, resolution int, pth string) error { - // Create a mesh out of finite elements. - m, _ := mesh.NewHex8(s, render.NewMarchingCubesFEUniform(resolution)) - - lyrStart := 0 - lyrEnd := 20 + m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to a file. - // - // Units are mm,N,sec. - // Force per area = N/mm2 or MPa - // Mass density = Ns2/mm4 - // Refer to the "Units" chapter of: - // http://www.dhondt.de/ccx_2.20.pdf - // - // Mechanical properties are based on typical SLA resins. - // - // TODO: Correct resin specifications. - err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + err := m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) if err != nil { return err } - return nil -} -// 20-node hexahedral elements. -func hex20(s sdf.SDF3, resolution int, pth string) error { - // Create a mesh out of finite elements. - m, _ := mesh.NewHex20(s, render.NewMarchingCubesFEUniform(resolution)) - - lyrStart := 0 - lyrEnd := 20 - - // Write just some layers of mesh to a file. - // - // Units are mm,N,sec. - // Force per area = N/mm2 or MPa - // Mass density = Ns2/mm4 - // Refer to the "Units" chapter of: - // http://www.dhondt.de/ccx_2.20.pdf - // - // Mechanical properties are based on typical SLA resins. - // - // TODO: Correct resin specifications. - err := m.WriteInpLayers(pth, lyrStart, lyrEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) - if err != nil { - return err - } return nil } @@ -123,22 +51,38 @@ func main() { log.Fatalf("error: %s", err) } - err = tet4(teapotSdf, 80, "teapot-tet4.inp") + // tet4 i.e. 4-node tetrahedron + err = fe(teapotSdf, 80, render.Linear, render.Tetrahedral, "teapot-tet4.inp", 0, 20) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet10 i.e. 10-node tetrahedron + err = fe(teapotSdf, 80, render.Quadratic, render.Tetrahedral, "teapot-tet10.inp", 0, 20) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 i.e. 8-node hexahedron + err = fe(teapotSdf, 80, render.Linear, render.Hexahedral, "teapot-hex8.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } - err = tet10(teapotSdf, 80, "teapot-tet10.inp") + // hex20 i.e. 20-node hexahedron + err = fe(teapotSdf, 80, render.Quadratic, render.Hexahedral, "teapot-hex20.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } - err = hex8(teapotSdf, 80, "teapot-hex8.inp") + // hex8 and tet4 + err = fe(teapotSdf, 80, render.Linear, render.Both, "teapot-hex8tet4.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } - err = hex20(teapotSdf, 80, "teapot-hex20.inp") + // hex20 and tet10 + err = fe(teapotSdf, 80, render.Quadratic, render.Both, "teapot-hex20tet10.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } diff --git a/render/fe.go b/render/fe.go new file mode 100644 index 000000000..a401fd897 --- /dev/null +++ b/render/fe.go @@ -0,0 +1,41 @@ +package render + +import ( + "sync" + + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// Fe is a finite element. +type Fe struct { + // Coordinates of nodes or vertices. + V []v3.Vec + // Coordinates of the voxel to which the element belongs. + X int + Y int + Z int +} + +//----------------------------------------------------------------------------- + +// writeFe writes a stream of finite elements to an array. +func writeFe(wg *sync.WaitGroup, elements *[]Fe) chan<- []*Fe { + // External code writes to this channel. + // This goroutine reads the channel and stores finite elements. + c := make(chan []*Fe) + + wg.Add(1) + go func() { + defer wg.Done() + // read finite elements from the channel and handle them + for fes := range c { + for _, fe := range fes { + *elements = append(*elements, *fe) + } + } + }() + + return c +} + +//----------------------------------------------------------------------------- diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index ee6d94140..b5d36ad55 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -2,73 +2,30 @@ package buffer // Index buffer for a mesh of finite elements. type IB struct { - // Every NodesPerElement indices would correspond to a finite element. - // It's kept low-level for performance. - // Finite elements are stored by their layer on Z axis. - I [][]uint32 - NodesPerElement int + Grid *VoxelGrid } -func NewIB(layerCount, nodesPerElement int) *IB { - if nodesPerElement < 1 { - panic("nodes per finite element must be positive") - } - +func NewIB(voxelsX, voxelsY, voxelsZ int) *IB { ib := IB{ - I: [][]uint32{}, - NodesPerElement: nodesPerElement, - } - - // Initialize. - ib.I = make([][]uint32, layerCount) - for l := 0; l < layerCount; l++ { - ib.I[l] = make([]uint32, 0) + Grid: NewVoxelGrid(voxelsX, voxelsY, voxelsZ), } return &ib } // Add a finite element to buffer. -// Layer number and nodes are input. +// Voxel coordinate and nodes are input. // The node numbering should follow the convention of CalculiX. // http://www.dhondt.de/ccx_2.20.pdf -func (ib *IB) AddFE(l int, nodes []uint32) { - if len(nodes) != ib.NodesPerElement { - // Don't return error. - // Since this function is going to be called by heavy loops. - // More efficient this way. Right? - panic("bad sizes: nodes of finite element") - } - ib.I[l] = append(ib.I[l], nodes...) +func (ib *IB) AddFE(x, y, z int, nodes []uint32) { + ib.Grid.Append(x, y, z, NewElement(nodes)) } -// Number of layers along the Z axis. -func (ib *IB) LayerCount() int { - return len(ib.I) +// To iterate over all voxels and get elements inside each voxel and do stuff with them. +func (ib *IB) Iterate(f func(int, int, int, []*Element)) { + ib.Grid.Iterate(f) } -// Number of finite elements on a layer. -func (ib *IB) FECountOnLayer(l int) int { - return len(ib.I[l]) / ib.NodesPerElement -} - -// Number of finite elements for all layers. -func (ib *IB) FECount() int { - var count int - for _, l := range ib.I { - count += len(l) / ib.NodesPerElement - } - return count -} - -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of FE on layer. -// Don't return error to increase performance. -func (ib *IB) FEIndicies(l, i int) []uint32 { - indices := make([]uint32, ib.NodesPerElement) - for n := 0; n < ib.NodesPerElement; n++ { - indices[n] = ib.I[l][i*ib.NodesPerElement+n] - } - return indices +func (ib *IB) Size() (int, int, int) { + return ib.Grid.Size() } diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 57c909f16..de8a45a70 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -4,19 +4,28 @@ type Element struct { Nodes []uint32 // Node indices } -func (e *Element) Type() string { - el := "" - count := len(e.Nodes) - if count == 4 { - el = "C3D4" - } else if count == 10 { - el = "C3D10" - } else if count == 8 { - el = "C3D8" - } else if count == 20 { - el = "C3D20R" +// Declare the enum using iota and const +type ElementType int + +const ( + C3D4 ElementType = iota + 1 + C3D10 + C3D8 + C3D20R + Unknown +) + +func (e *Element) Type() ElementType { + if len(e.Nodes) == 4 { + return C3D4 + } else if len(e.Nodes) == 10 { + return C3D10 + } else if len(e.Nodes) == 8 { + return C3D8 + } else if len(e.Nodes) == 20 { + return C3D20R } - return el + return Unknown } func NewElement(nodes []uint32) *Element { @@ -43,6 +52,10 @@ func NewVoxelGrid(x, y, z int) *VoxelGrid { } } +func (vg *VoxelGrid) Size() (int, int, int) { + return vg.lenX, vg.lenY, vg.lenZ +} + // To get all the elements inside a voxel. func (vg *VoxelGrid) Get(x, y, z int) []*Element { return vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] @@ -59,12 +72,12 @@ func (vg *VoxelGrid) Append(x, y, z int, value *Element) { } // To iterate over all voxels and get elements inside each voxel and do stuff with them. -func (vg *VoxelGrid) Iterate(f func([]*Element)) { +func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { for z := 0; z < vg.lenZ; z++ { for y := 0; y < vg.lenY; y++ { for x := 0; x < vg.lenX; x++ { value := vg.Get(x, y, z) - f(value) + f(x, y, z, value) } } } diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go new file mode 100644 index 000000000..12ea56072 --- /dev/null +++ b/render/finiteelements/mesh/fem.go @@ -0,0 +1,106 @@ +package mesh + +import ( + "github.com/deadsy/sdfx/render" + "github.com/deadsy/sdfx/render/finiteelements/buffer" + "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// Fem is a mesh of finite elements. +// A sophisticated data structure for mesh is required. +// The repeated nodes would be removed. +// The element connectivity would be created with unique nodes. +type Fem struct { + // Index buffer. + IBuff *buffer.IB + // Vertex buffer. + VBuff *buffer.VB +} + +// NewFem returns a new mesh and number of its layers along Z-axis. +func NewFem(s sdf.SDF3, r render.RenderFE) (*Fem, int) { + fes := render.ToFem(s, r) + + layersX, layersY, layersZ := r.LayerCounts(s) + + m := newFem(layersX, layersY, layersZ) + + // Fill out the mesh with finite elements. + for _, fe := range fes { + m.addFE(fe.X, fe.Y, fe.Z, fe.V) + } + + defer m.VBuff.DestroyHashTable() + + return m, layersZ +} + +func newFem(layersX, layersY, layersZ int) *Fem { + return &Fem{ + IBuff: buffer.NewIB(layersX, layersY, layersZ), + VBuff: buffer.NewVB(), + } +} + +func (m *Fem) Size() (int, int, int) { + return m.IBuff.Size() +} + +// Add a finite element. +// Voxel coordinate and nodes are input. +// The node numbering should follow the convention of CalculiX. +// http://www.dhondt.de/ccx_2.20.pdf +func (m *Fem) addFE(x, y, z int, nodes []v3.Vec) { + indices := make([]uint32, len(nodes)) + for n := 0; n < len(nodes); n++ { + indices[n] = m.addVertex(nodes[n]) + } + m.IBuff.AddFE(x, y, z, indices) +} + +func (m *Fem) addVertex(vert v3.Vec) uint32 { + return m.VBuff.Id(vert) +} + +func (m *Fem) vertexCount() int { + return m.VBuff.VertexCount() +} + +func (m *Fem) vertex(i uint32) v3.Vec { + return m.VBuff.Vertex(i) +} + +// To iterate over all voxels and get elements inside each voxel and do stuff with them. +func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { + m.IBuff.Iterate(f) +} + +// WriteInp writes mesh to ABAQUS or CalculiX `inp` file. +func (m *Fem) WriteInp( + path string, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + _, _, layersZ := m.IBuff.Size() + return m.WriteInpLayers(path, 0, layersZ, layersFixed, massDensity, youngModulus, poissonRatio) +} + +// WriteInpLayers writes specific layers of mesh to ABAQUS or CalculiX `inp` file. +// Result would include start layer. +// Result would exclude end layer. +func (m *Fem) WriteInpLayers( + path string, + layerStart, layerEnd int, + layersFixed []int, + massDensity float32, + youngModulus float32, + poissonRatio float32, +) error { + inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) + return inp.Write() +} + +//----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/hex20.go b/render/finiteelements/mesh/hex20.go deleted file mode 100644 index 030c65db0..000000000 --- a/render/finiteelements/mesh/hex20.go +++ /dev/null @@ -1,147 +0,0 @@ -package mesh - -import ( - "github.com/deadsy/sdfx/render" - "github.com/deadsy/sdfx/render/finiteelements/buffer" - "github.com/deadsy/sdfx/sdf" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Hex20 is a mesh of 20-node hexahedra. -// A sophisticated data structure for mesh is required. -// The repeated nodes would be removed. -// The element connectivity would be created with unique nodes. -type Hex20 struct { - // Index buffer. - IBuff *buffer.IB - // Vertex buffer. - VBuff *buffer.VB -} - -// NewHex20 returns a new mesh and number of its layers along Z-axis. -func NewHex20(s sdf.SDF3, r render.RenderFE) (*Hex20, int) { - fes := render.ToHex20(s, r) - - _, _, layerCountZ := r.LayerCounts(s) - - m := newHex20(layerCountZ) - - // Fill out the mesh with finite elements. - for _, fe := range fes { - nodes := [20]v3.Vec{} - for n := 0; n < 20; n++ { - nodes[n] = fe.V[n] - } - m.addFE(fe.Layer, nodes) - } - - defer m.VBuff.DestroyHashTable() - - return m, layerCountZ -} - -func newHex20(layerCount int) *Hex20 { - return &Hex20{ - IBuff: buffer.NewIB(layerCount, 20), - VBuff: buffer.NewVB(), - } -} - -// Npe returns number of nodes per element. -func (m *Hex20) Npe() int { - return 20 -} - -// Add a finite element to mesh. -// Layer number and nodes are input. -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (m *Hex20) addFE(l int, nodes [20]v3.Vec) { - indices := [20]uint32{} - for n := 0; n < 20; n++ { - indices[n] = m.addVertex(nodes[n]) - } - m.IBuff.AddFE(l, indices[:]) -} - -func (m *Hex20) addVertex(vert v3.Vec) uint32 { - return m.VBuff.Id(vert) -} - -func (m *Hex20) vertexCount() int { - return m.VBuff.VertexCount() -} - -func (m *Hex20) vertex(i uint32) v3.Vec { - return m.VBuff.Vertex(i) -} - -// Number of layers along the Z axis. -func (m *Hex20) layerCount() int { - return m.IBuff.LayerCount() -} - -// Number of finite elements on a layer. -func (m *Hex20) feCountOnLayer(l int) int { - return m.IBuff.FECountOnLayer(l) -} - -// Number of finite elements for all layers. -func (m *Hex20) feCount() int { - return m.IBuff.FECount() -} - -// Get a finite element. -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *Hex20) feIndicies(l, i int) []uint32 { - return m.IBuff.FEIndicies(l, i) -} - -// Get a finite element. -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *Hex20) feVertices(l, i int) []v3.Vec { - indices := m.IBuff.FEIndicies(l, i) - vertices := make([]v3.Vec, 20) - for n := 0; n < 20; n++ { - vertices[n] = m.VBuff.Vertex(indices[n]) - } - return vertices -} - -// WriteInp saves mesh to ABAQUS or CalculiX `inp` file. -// Units of measurement are mm,N,s,K. -// Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *Hex20) WriteInp( - path string, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) -} - -// WriteInpLayers saves specific layers of mesh to ABAQUS or CalculiX `inp` file. -// Result would include start layer. -// Result would exclude end layer. -// Units of measurement are mm,N,s,K. -// Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *Hex20) WriteInpLayers( - path string, - layerStart, layerEnd int, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) - return inp.Write() -} - -//----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/hex8.go b/render/finiteelements/mesh/hex8.go deleted file mode 100644 index 62c9cc97f..000000000 --- a/render/finiteelements/mesh/hex8.go +++ /dev/null @@ -1,147 +0,0 @@ -package mesh - -import ( - "github.com/deadsy/sdfx/render" - "github.com/deadsy/sdfx/render/finiteelements/buffer" - "github.com/deadsy/sdfx/sdf" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Hex8 is a mesh of 8-node hexahedra. -// A sophisticated data structure for mesh is required. -// The repeated nodes would be removed. -// The element connectivity would be created with unique nodes. -type Hex8 struct { - // Index buffer. - IBuff *buffer.IB - // Vertex buffer. - VBuff *buffer.VB -} - -// NewHex8 returns a new mesh and number of its layers along Z-axis. -func NewHex8(s sdf.SDF3, r render.RenderFE) (*Hex8, int) { - fes := render.ToHex8(s, r) - - _, _, layerCountZ := r.LayerCounts(s) - - m := newHex8(layerCountZ) - - // Fill out the mesh with finite elements. - for _, fe := range fes { - nodes := [8]v3.Vec{} - for n := 0; n < 8; n++ { - nodes[n] = fe.V[n] - } - m.addFE(fe.Layer, nodes) - } - - defer m.VBuff.DestroyHashTable() - - return m, layerCountZ -} - -func newHex8(layerCount int) *Hex8 { - return &Hex8{ - IBuff: buffer.NewIB(layerCount, 8), - VBuff: buffer.NewVB(), - } -} - -// Npe returns number of nodes per element. -func (m *Hex8) Npe() int { - return 8 -} - -// Add a finite element to mesh. -// Layer number and nodes are input. -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (m *Hex8) addFE(l int, nodes [8]v3.Vec) { - indices := [8]uint32{} - for n := 0; n < 8; n++ { - indices[n] = m.addVertex(nodes[n]) - } - m.IBuff.AddFE(l, indices[:]) -} - -func (m *Hex8) addVertex(vert v3.Vec) uint32 { - return m.VBuff.Id(vert) -} - -func (m *Hex8) vertexCount() int { - return m.VBuff.VertexCount() -} - -func (m *Hex8) vertex(i uint32) v3.Vec { - return m.VBuff.Vertex(i) -} - -// Number of layers along the Z axis. -func (m *Hex8) layerCount() int { - return m.IBuff.LayerCount() -} - -// Number of finite elements on a layer. -func (m *Hex8) feCountOnLayer(l int) int { - return m.IBuff.FECountOnLayer(l) -} - -// Number of finite elements for all layers. -func (m *Hex8) feCount() int { - return m.IBuff.FECount() -} - -// Get a finite element. -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *Hex8) feIndicies(l, i int) []uint32 { - return m.IBuff.FEIndicies(l, i) -} - -// Get a finite element. -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *Hex8) feVertices(l, i int) []v3.Vec { - indices := m.IBuff.FEIndicies(l, i) - vertices := make([]v3.Vec, 8) - for n := 0; n < 8; n++ { - vertices[n] = m.VBuff.Vertex(indices[n]) - } - return vertices -} - -// WriteInp saves mesh to ABAQUS or CalculiX `inp` file. -// Units of measurement are mm,N,s,K. -// Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *Hex8) WriteInp( - path string, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) -} - -// WriteInpLayers saves specific layers of mesh to ABAQUS or CalculiX `inp` file. -// Result would include start layer. -// Result would exclude end layer. -// Units of measurement are mm,N,s,K. -// Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *Hex8) WriteInpLayers( - path string, - layerStart, layerEnd int, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) - return inp.Write() -} - -//----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index f0b37c27d..aa342b8a9 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -12,13 +12,19 @@ import ( // Inp writes different types of finite elements as ABAQUS or CalculiX `inp` file. type Inp struct { // Finite elements mesh. - Mesh FE + Mesh *Fem // Output `inp` file path. Path string // For writing nodes to a separate file. PathNodes string // For writing elements to a separate file. - PathEls string + PathElsC3D4 string + // For writing elements to a separate file. + PathElsC3D10 string + // For writing elements to a separate file. + PathElsC3D8 string + // For writing elements to a separate file. + PathElsC3D20R string // For writing boundary conditions to a separate file. PathBou string // Output `inp` file would include start layer. @@ -33,29 +39,38 @@ type Inp struct { MassDensity float32 YoungModulus float32 PoissonRatio float32 + // Just a counter to keep track of written elements + eleID uint32 + // Just a counter to keep track of written nodes + nextNode uint32 + // Just a counter to keep track of written boundaries + nextNodeBou uint32 } // NewInp sets up a new writer. func NewInp( - m FE, + m *Fem, path string, layerStart, layerEnd int, layersFixed []int, massDensity float32, youngModulus float32, poissonRatio float32, ) *Inp { return &Inp{ - Mesh: m, - Path: path, - PathNodes: path + ".nodes", - PathEls: path + ".elements", - PathBou: path + ".boundary", - LayerStart: layerStart, - LayerEnd: layerEnd, - LayersFixed: layersFixed, - TempVBuff: buffer.NewVB(), - MassDensity: massDensity, - YoungModulus: youngModulus, - PoissonRatio: poissonRatio, + Mesh: m, + Path: path, + PathNodes: path + ".nodes", + PathElsC3D4: path + ".elements_C3D4", + PathElsC3D10: path + ".elements_C3D10", + PathElsC3D8: path + ".elements_C3D8", + PathElsC3D20R: path + ".elements_C3D20R", + PathBou: path + ".boundary", + LayerStart: layerStart, + LayerEnd: layerEnd, + LayersFixed: layersFixed, + TempVBuff: buffer.NewVB(), + MassDensity: massDensity, + YoungModulus: youngModulus, + PoissonRatio: poissonRatio, } } @@ -74,89 +89,57 @@ func (inp *Inp) Write() error { // Write nodes. - _, err = f.WriteString("*NODE\n") - if err != nil { - return err - } - // Include a separate file to avoid cluttering the `inp` file. _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathNodes)) if err != nil { return err } - // Write to a separate file to avoid cluttering the `inp` file. - fNodes, err := os.Create(inp.PathNodes) - if err != nil { - return err - } - defer fNodes.Close() - // Temp buffer is just to avoid writing repeated nodes into the `inpt` file. defer inp.TempVBuff.DestroyHashTable() - err = inp.writeNodes(fNodes) + err = inp.writeNodes() if err != nil { return err } // Write elements. - ElementType := "" - if inp.Mesh.Npe() == 4 { - ElementType = "C3D4" - } else if inp.Mesh.Npe() == 10 { - ElementType = "C3D10" - } else if inp.Mesh.Npe() == 8 { - ElementType = "C3D8" - } else if inp.Mesh.Npe() == 20 { - ElementType = "C3D20R" - } - - _, err = f.WriteString(fmt.Sprintf("*ELEMENT, TYPE=%s, ELSET=Eall\n", ElementType)) + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathElsC3D4)) if err != nil { return err } - // Include a separate file to avoid cluttering the `inp` file. - _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathEls)) + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathElsC3D10)) if err != nil { return err } - - // Write to a separate file to avoid cluttering the `inp` file. - fEls, err := os.Create(inp.PathEls) + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathElsC3D8)) if err != nil { return err } - defer fEls.Close() - - err = inp.writeElements(fEls) + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathElsC3D20R)) if err != nil { return err } - // Fix the degrees of freedom one through three for all nodes on specific layers. - - _, err = f.WriteString("*BOUNDARY\n") + err = inp.writeElements() if err != nil { return err } + // Fix the degrees of freedom one through three for all nodes on specific layers. + // Include a separate file to avoid cluttering the `inp` file. _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathBou)) if err != nil { return err } - // Write to a separate file to avoid cluttering the `inp` file. - fBou, err := os.Create(inp.PathBou) - if err != nil { - return err - } - defer fBou.Close() - - err = inp.writeBoundary(fBou) + err = inp.writeBoundary() if err != nil { return err } @@ -165,7 +148,8 @@ func (inp *Inp) Write() error { } func (inp *Inp) writeHeader(f *os.File) error { - if 0 <= inp.LayerStart && inp.LayerStart < inp.LayerEnd && inp.LayerEnd <= inp.Mesh.layerCount() { + _, _, layersZ := inp.Mesh.Size() + if 0 <= inp.LayerStart && inp.LayerStart < inp.LayerEnd && inp.LayerEnd <= layersZ { // Good. } else { return fmt.Errorf("start or end layer is beyond range") @@ -184,106 +168,220 @@ func (inp *Inp) writeHeader(f *os.File) error { return nil } -func (inp *Inp) writeNodes(f *os.File) error { - // Declare vars outside loop for efficiency. - var err error - nodes := make([]v3.Vec, 0, inp.Mesh.Npe()) - ids := make([]uint32, inp.Mesh.Npe()) - var nextNode uint32 = 1 // ID starts from one not zero. - for l := inp.LayerStart; l < inp.LayerEnd; l++ { - for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { - // Get the node IDs. - nodes = inp.Mesh.feVertices(l, i) - for n := 0; n < inp.Mesh.Npe(); n++ { - ids[n] = inp.TempVBuff.Id(nodes[n]) +func (inp *Inp) writeNodes() error { + // Write to a separate file to avoid cluttering the `inp` file. + f, err := os.Create(inp.PathNodes) + if err != nil { + return err + } + defer f.Close() + + _, err = f.WriteString("*NODE\n") + if err != nil { + return err + } + + var process func(int, int, int, []*buffer.Element) + + inp.nextNode = 1 // ID starts from one not zero. + + process = func(x, y, z int, els []*buffer.Element) { + if z >= inp.LayerStart && z < inp.LayerEnd { + // Good. + } else { + return + } + + for _, el := range els { + vertices := make([]v3.Vec, len(el.Nodes)) + ids := make([]uint32, len(el.Nodes)) + for n := 0; n < len(el.Nodes); n++ { + vertices[n] = inp.Mesh.vertex(el.Nodes[n]) + ids[n] = inp.TempVBuff.Id(vertices[n]) } // Write the node IDs. - for n := 0; n < inp.Mesh.Npe(); n++ { + for n := 0; n < len(el.Nodes); n++ { // Only write node if it's not already written to file. - if ids[n]+1 == nextNode { + if ids[n]+1 == inp.nextNode { // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(nodes[n].X), float32(nodes[n].Y), float32(nodes[n].Z))) + _, err = f.WriteString(fmt.Sprintf("%d,%f,%f,%f\n", ids[n]+1, float32(vertices[n].X), float32(vertices[n].Y), float32(vertices[n].Z))) if err != nil { - return err + panic("Couldn't write node to file: " + err.Error()) } - nextNode++ + inp.nextNode++ } } } } + inp.Mesh.iterate(process) + return nil } -func (inp *Inp) writeElements(f *os.File) error { - // Declare vars outside loop for efficiency. - var err error - nodes := make([]v3.Vec, 0, inp.Mesh.Npe()) - ids := make([]uint32, inp.Mesh.Npe()) - var eleID uint32 - for l := inp.LayerStart; l < inp.LayerEnd; l++ { - for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { - nodes = inp.Mesh.feVertices(l, i) - for n := 0; n < inp.Mesh.Npe(); n++ { - ids[n] = inp.TempVBuff.Id(nodes[n]) +func (inp *Inp) writeElements() error { + // Write to a separate file to avoid cluttering the `inp` file. + fC3D4, err := os.Create(inp.PathElsC3D4) + if err != nil { + return err + } + defer fC3D4.Close() + + // Write to a separate file to avoid cluttering the `inp` file. + fC3D10, err := os.Create(inp.PathElsC3D10) + if err != nil { + return err + } + defer fC3D10.Close() + + // Write to a separate file to avoid cluttering the `inp` file. + fC3D8, err := os.Create(inp.PathElsC3D8) + if err != nil { + return err + } + defer fC3D8.Close() + + // Write to a separate file to avoid cluttering the `inp` file. + fC3D20R, err := os.Create(inp.PathElsC3D20R) + if err != nil { + return err + } + defer fC3D20R.Close() + + _, err = fC3D4.WriteString(fmt.Sprintf("*ELEMENT, TYPE=%s, ELSET=eC3D4\n", "C3D4")) + if err != nil { + return err + } + + _, err = fC3D10.WriteString(fmt.Sprintf("*ELEMENT, TYPE=%s, ELSET=e3D10\n", "C3D10")) + if err != nil { + return err + } + + _, err = fC3D8.WriteString(fmt.Sprintf("*ELEMENT, TYPE=%s, ELSET=eC3D8\n", "C3D8")) + if err != nil { + return err + } + + _, err = fC3D20R.WriteString(fmt.Sprintf("*ELEMENT, TYPE=%s, ELSET=eC3D20R\n", "C3D20R")) + if err != nil { + return err + } + + // Define a function variable with the signature + var process func(int, int, int, []*buffer.Element) + // Assign a function literal to the variable + process = func(x, y, z int, els []*buffer.Element) { + if z >= inp.LayerStart && z < inp.LayerEnd { + // Good. + } else { + return + } + for _, el := range els { + ids := make([]uint32, len(el.Nodes)) + for n := 0; n < len(el.Nodes); n++ { + vertex := inp.Mesh.vertex(el.Nodes[n]) + ids[n] = inp.TempVBuff.Id(vertex) } // ID starts from one not zero. - if inp.Mesh.Npe() == 4 { - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1)) - } else if inp.Mesh.Npe() == 10 { - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1)) - } else if inp.Mesh.Npe() == 8 { - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) - } else if inp.Mesh.Npe() == 20 { - // There should not be more than 16 entries in a line; - // That's why there is new line in the middle. - // Refer to CalculiX solver documentation: - // http://www.dhondt.de/ccx_2.20.pdf - _, err = f.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\n%d,%d,%d,%d,%d\n", eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1, ids[10]+1, ids[11]+1, ids[12]+1, ids[13]+1, ids[14]+1, ids[15]+1, ids[16]+1, ids[17]+1, ids[18]+1, ids[19]+1)) + switch el.Type() { + case buffer.C3D4: + { + _, err = fC3D4.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d\n", inp.eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1)) + } + case buffer.C3D10: + { + _, err = fC3D10.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", inp.eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1)) + } + case buffer.C3D8: + { + _, err = fC3D8.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", inp.eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1)) + } + case buffer.C3D20R: + { + // There should not be more than 16 entries in a line; + // That's why there is new line in the middle. + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + _, err = fC3D20R.WriteString(fmt.Sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\n%d,%d,%d,%d,%d\n", inp.eleID+1, ids[0]+1, ids[1]+1, ids[2]+1, ids[3]+1, ids[4]+1, ids[5]+1, ids[6]+1, ids[7]+1, ids[8]+1, ids[9]+1, ids[10]+1, ids[11]+1, ids[12]+1, ids[13]+1, ids[14]+1, ids[15]+1, ids[16]+1, ids[17]+1, ids[18]+1, ids[19]+1)) + } + case buffer.Unknown: + { + fmt.Println("Element has unknown type :(") + } } if err != nil { - return err + panic("Couldn't write finite element to file: " + err.Error()) } - eleID++ + + inp.eleID++ } } + inp.Mesh.iterate(process) + return nil } -func (inp *Inp) writeBoundary(f *os.File) error { - // Declare vars outside loop for efficiency. - var err error - nodes := make([]v3.Vec, 0, inp.Mesh.Npe()) - ids := make([]uint32, inp.Mesh.Npe()) - var nextNode uint32 = 1 // ID starts from one not zero. - for l := range inp.LayersFixed { - for i := 0; i < inp.Mesh.feCountOnLayer(l); i++ { - nodes = inp.Mesh.feVertices(l, i) - for n := 0; n < inp.Mesh.Npe(); n++ { - ids[n] = inp.TempVBuff.Id(nodes[n]) +func (inp *Inp) writeBoundary() error { + // Write to a separate file to avoid cluttering the `inp` file. + f, err := os.Create(inp.PathBou) + if err != nil { + return err + } + defer f.Close() + + _, err = f.WriteString("*BOUNDARY\n") + if err != nil { + return err + } + + var process func(int, int, int, []*buffer.Element) + + inp.nextNodeBou = 1 // ID starts from one not zero. + + process = func(x, y, z int, els []*buffer.Element) { + var isLayerFixed bool + for _, l := range inp.LayersFixed { + if l == z { + isLayerFixed = true + } + } + + if !isLayerFixed { + return + } + + for _, el := range els { + vertices := make([]v3.Vec, len(el.Nodes)) + ids := make([]uint32, len(el.Nodes)) + for n := 0; n < len(el.Nodes); n++ { + vertices[n] = inp.Mesh.vertex(el.Nodes[n]) + ids[n] = inp.TempVBuff.Id(vertices[n]) } // Write the node IDs. - for n := 0; n < inp.Mesh.Npe(); n++ { + for n := 0; n < len(el.Nodes); n++ { // Only write node if it's not already written to file. - if ids[n]+1 == nextNode { + if ids[n]+1 == inp.nextNodeBou { // ID starts from one not zero. _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) if err != nil { - return err + panic("Couldn't write boundary to file: " + err.Error()) } - nextNode++ + inp.nextNodeBou++ } } } } + inp.Mesh.iterate(process) + return nil } @@ -313,7 +411,25 @@ func (inp *Inp) writeFooter(f *os.File) error { } // Assign material to all elements - _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=Eall\n") + _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=eC3D4\n") + if err != nil { + return err + } + + // Assign material to all elements + _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=e3D10\n") + if err != nil { + return err + } + + // Assign material to all elements + _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=eC3D8\n") + if err != nil { + return err + } + + // Assign material to all elements + _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=eC3D20R\n") if err != nil { return err } @@ -340,7 +456,19 @@ func (inp *Inp) writeFooter(f *os.File) error { // // Refer to CalculiX solver documentation: // http://www.dhondt.de/ccx_2.20.pdf - _, err = f.WriteString("Eall,GRAV,9810.,0.,0.,1.\n") + _, err = f.WriteString("eC3D4,GRAV,9810.,0.,0.,1.\n") + if err != nil { + return err + } + _, err = f.WriteString("e3D10,GRAV,9810.,0.,0.,1.\n") + if err != nil { + return err + } + _, err = f.WriteString("eC3D8,GRAV,9810.,0.,0.,1.\n") + if err != nil { + return err + } + _, err = f.WriteString("eC3D20R,GRAV,9810.,0.,0.,1.\n") if err != nil { return err } diff --git a/render/finiteelements/mesh/mesh.go b/render/finiteelements/mesh/mesh.go index 701b61cea..9115fd5a1 100644 --- a/render/finiteelements/mesh/mesh.go +++ b/render/finiteelements/mesh/mesh.go @@ -1,24 +1,5 @@ // Package mesh provides convenient types & functions for meshes consisting of finite elements. -// Like 4-node tetrahedra, 8-node and 20-node hexahedra. +// Like 4-node & 10-node tetrahedra, 8-node & 20-node hexahedra. package mesh -import v3 "github.com/deadsy/sdfx/vec/v3" - -// FE is a dynamic type for a mesh of finite elements like Tet4, Hex8, Hex20, ... -type FE interface { - // Number of nodes per element. - Npe() int - // Number of layers along the Z axis. - layerCount() int - // Number of finite elements on a layer. - feCountOnLayer(l int) int - // Total number of elements for all layers. - feCount() int - // Get a finite element. - // FE vertices are returned. - // Layer index is input. - // FE index on layer is input. - feVertices(l, i int) []v3.Vec -} - //----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/tet10.go b/render/finiteelements/mesh/tet10.go deleted file mode 100644 index fb8d8f787..000000000 --- a/render/finiteelements/mesh/tet10.go +++ /dev/null @@ -1,147 +0,0 @@ -package mesh - -import ( - "github.com/deadsy/sdfx/render" - "github.com/deadsy/sdfx/render/finiteelements/buffer" - "github.com/deadsy/sdfx/sdf" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Tet10 is a mesh of 10-node tetrahedra. -// A sophisticated data structure for mesh is required. -// The repeated nodes would be removed. -// The element connectivity would be created with unique nodes. -type Tet10 struct { - // Index buffer. - IBuff *buffer.IB - // Vertex buffer. - VBuff *buffer.VB -} - -// NewTet10 returns a new mesh and number of its layers along Z-axis. -func NewTet10(s sdf.SDF3, r render.RenderFE) (*Tet10, int) { - fes := render.ToTet10(s, r) - - _, _, layerCountZ := r.LayerCounts(s) - - m := newTet10(layerCountZ) - - // Fill out the mesh with finite elements. - for _, fe := range fes { - nodes := [10]v3.Vec{} - for n := 0; n < 10; n++ { - nodes[n] = fe.V[n] - } - m.addFE(fe.Layer, nodes) - } - - defer m.VBuff.DestroyHashTable() - - return m, layerCountZ -} - -func newTet10(layerCount int) *Tet10 { - return &Tet10{ - IBuff: buffer.NewIB(layerCount, 10), - VBuff: buffer.NewVB(), - } -} - -// Npe returns number of nodes per element. -func (m *Tet10) Npe() int { - return 10 -} - -// Add a finite element to mesh. -// Layer number and nodes are input. -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (m *Tet10) addFE(l int, nodes [10]v3.Vec) { - indices := [10]uint32{} - for n := 0; n < 10; n++ { - indices[n] = m.addVertex(nodes[n]) - } - m.IBuff.AddFE(l, indices[:]) -} - -func (m *Tet10) addVertex(vert v3.Vec) uint32 { - return m.VBuff.Id(vert) -} - -func (m *Tet10) vertexCount() int { - return m.VBuff.VertexCount() -} - -func (m *Tet10) vertex(i uint32) v3.Vec { - return m.VBuff.Vertex(i) -} - -// Number of layers along the Z axis. -func (m *Tet10) layerCount() int { - return m.IBuff.LayerCount() -} - -// Number of finite elements on a layer. -func (m *Tet10) feCountOnLayer(l int) int { - return m.IBuff.FECountOnLayer(l) -} - -// Number of finite elements for all layers. -func (m *Tet10) feCount() int { - return m.IBuff.FECount() -} - -// Get a finite element. -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *Tet10) feIndicies(l, i int) []uint32 { - return m.IBuff.FEIndicies(l, i) -} - -// Get a finite element. -// Layer number is input. -// FE index on layer is input. -// FE index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *Tet10) feVertices(l, i int) []v3.Vec { - indices := m.IBuff.FEIndicies(l, i) - vertices := make([]v3.Vec, 10) - for n := 0; n < 10; n++ { - vertices[n] = m.VBuff.Vertex(indices[n]) - } - return vertices -} - -// WriteInp saves mesh to ABAQUS or CalculiX `inp` file. -// Units of measurement are mm,N,s,K. -// Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *Tet10) WriteInp( - path string, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) -} - -// WriteInpLayers saves specific layers of mesh to ABAQUS or CalculiX `inp` file. -// Result would include start layer. -// Result would exclude end layer. -// Units of measurement are mm,N,s,K. -// Refer to https://engineering.stackexchange.com/q/54454/15178 -func (m *Tet10) WriteInpLayers( - path string, - layerStart, layerEnd int, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) - return inp.Write() -} - -//----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/tet4.go b/render/finiteelements/mesh/tet4.go deleted file mode 100644 index 373aa1f44..000000000 --- a/render/finiteelements/mesh/tet4.go +++ /dev/null @@ -1,139 +0,0 @@ -package mesh - -import ( - "github.com/deadsy/sdfx/render" - "github.com/deadsy/sdfx/render/finiteelements/buffer" - "github.com/deadsy/sdfx/sdf" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Tet4 is a mesh of 4-node tetrahedra. -// A sophisticated data structure for mesh is required. -// The repeated nodes would be removed. -// The element connectivity would be created with unique nodes. -type Tet4 struct { - // Index buffer. - IBuff *buffer.IB - // Vertex buffer. - VBuff *buffer.VB -} - -// NewTet4 returns a new mesh and number of its layers along Z-axis. -func NewTet4(s sdf.SDF3, r render.RenderFE) (*Tet4, int) { - fes := render.ToTet4(s, r) - - _, _, layerCountZ := r.LayerCounts(s) - - m := newTet4(layerCountZ) - - // Fill out the mesh with finite elements. - for _, fe := range fes { - m.addFE(fe.Layer, [4]v3.Vec{fe.V[0], fe.V[1], fe.V[2], fe.V[3]}) - } - - defer m.VBuff.DestroyHashTable() - - return m, layerCountZ -} - -func newTet4(layerCount int) *Tet4 { - return &Tet4{ - IBuff: buffer.NewIB(layerCount, 4), - VBuff: buffer.NewVB(), - } -} - -// Npe returns number of nodes per element. -func (m *Tet4) Npe() int { - return 4 -} - -// Add a finite element. -// Layer number and nodes are input. -// The node numbering should follow the convention of CalculiX. -// http://www.dhondt.de/ccx_2.20.pdf -func (m *Tet4) addFE(l int, nodes [4]v3.Vec) { - indices := [4]uint32{} - for n := 0; n < 4; n++ { - indices[n] = m.addVertex(nodes[n]) - } - m.IBuff.AddFE(l, indices[:]) -} - -func (m *Tet4) addVertex(vert v3.Vec) uint32 { - return m.VBuff.Id(vert) -} - -func (m *Tet4) vertexCount() int { - return m.VBuff.VertexCount() -} - -func (m *Tet4) vertex(i uint32) v3.Vec { - return m.VBuff.Vertex(i) -} - -// Number of layers along the Z axis. -func (m *Tet4) layerCount() int { - return m.IBuff.LayerCount() -} - -// Number of tetrahedra on a layer. -func (m *Tet4) feCountOnLayer(l int) int { - return m.IBuff.FECountOnLayer(l) -} - -// Number of tetrahedra for all layers. -func (m *Tet4) feCount() int { - return m.IBuff.FECount() -} - -// Get a finite element. -// Layer number is input. -// Tetrahedron index on layer is input. -// Tetrahedron index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *Tet4) feIndicies(l, i int) []uint32 { - return m.IBuff.FEIndicies(l, i) -} - -// Get a finite element. -// Layer number is input. -// Tetrahedron index on layer is input. -// Tetrahedron index could be from 0 to number of tetrahedra on layer. -// Don't return error to increase performance. -func (m *Tet4) feVertices(l, i int) []v3.Vec { - indices := m.IBuff.FEIndicies(l, i) - vertices := make([]v3.Vec, 4) - for n := 0; n < 4; n++ { - vertices[n] = m.VBuff.Vertex(indices[n]) - } - return vertices -} - -// WriteInp writes mesh to ABAQUS or CalculiX `inp` file. -func (m *Tet4) WriteInp( - path string, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - return m.WriteInpLayers(path, 0, m.layerCount(), layersFixed, massDensity, youngModulus, poissonRatio) -} - -// WriteInpLayers writes specific layers of mesh to ABAQUS or CalculiX `inp` file. -// Result would include start layer. -// Result would exclude end layer. -func (m *Tet4) WriteInpLayers( - path string, - layerStart, layerEnd int, - layersFixed []int, - massDensity float32, - youngModulus float32, - poissonRatio float32, -) error { - inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio) - return inp.Write() -} - -//----------------------------------------------------------------------------- diff --git a/render/hex20.go b/render/hex20.go deleted file mode 100644 index 529795d37..000000000 --- a/render/hex20.go +++ /dev/null @@ -1,44 +0,0 @@ -package render - -import ( - "sync" - - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Hex20 is a 3D hexahedron consisting of 20 nodes. -// It's a kind of finite element, FE. -// https://en.wikipedia.org/wiki/Hexahedron -type Hex20 struct { - // Coordinates of 20 corner nodes or vertices. - V [20]v3.Vec - // The layer to which tetrahedron belongs. Layers are along Z axis. - // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store layer along Z axis. - // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. - // Sampling/marching algorithm is expected to return the layer to which a finite element belongs. - Layer int -} - -//----------------------------------------------------------------------------- - -// writeHex20 writes a stream of finite elements to an array. -func writeHex20(wg *sync.WaitGroup, hex20s *[]Hex20) chan<- []*Hex20 { - // External code writes to this channel. - // This goroutine reads the channel and stores finite elements. - c := make(chan []*Hex20) - - wg.Add(1) - go func() { - defer wg.Done() - // read finite elements from the channel and handle them - for fes := range c { - for _, fe := range fes { - *hex20s = append(*hex20s, *fe) - } - } - }() - - return c -} - -//----------------------------------------------------------------------------- diff --git a/render/hex8.go b/render/hex8.go deleted file mode 100644 index 964c1744a..000000000 --- a/render/hex8.go +++ /dev/null @@ -1,44 +0,0 @@ -package render - -import ( - "sync" - - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Hex8 is a 3D hexahedron consisting of 8 nodes. -// It's a kind of finite element, FE. -// https://en.wikipedia.org/wiki/Hexahedron -type Hex8 struct { - // Coordinates of 8 corner nodes or vertices. - V [8]v3.Vec - // The layer to which tetrahedron belongs. Layers are along Z axis. - // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store layer along Z axis. - // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. - // Sampling/marching algorithm is expected to return the layer to which a finite element belongs. - Layer int -} - -//----------------------------------------------------------------------------- - -// writeHex8 writes a stream of finite elements to an array. -func writeHex8(wg *sync.WaitGroup, hex8s *[]Hex8) chan<- []*Hex8 { - // External code writes to this channel. - // This goroutine reads the channel and stores finite elements. - c := make(chan []*Hex8) - - wg.Add(1) - go func() { - defer wg.Done() - // read finite elements from the channel and handle them - for fes := range c { - for _, fe := range fes { - *hex8s = append(*hex8s, *fe) - } - } - }() - - return c -} - -//----------------------------------------------------------------------------- diff --git a/render/marchfe.go b/render/marchfe.go index a1a910c9a..a16901739 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -13,15 +13,40 @@ import ( //----------------------------------------------------------------------------- +// A finite element can be linear or non-linear. +type Order int + +const ( + Linear Order = iota + 1 // 4-node tetrahedron and 8-node hexahedron + Quadratic // 10-node tetrahedron and 20-node hexahedron +) + +//----------------------------------------------------------------------------- + +// Two shapes of finite element can be generated: tetrahedral and hexahedral. +type Shape int + +const ( + Hexahedral Shape = iota + 1 + Tetrahedral + Both +) + +//----------------------------------------------------------------------------- + // MarchingCubesFEUniform renders using marching cubes with uniform space sampling. type MarchingCubesFEUniform struct { - meshCells int // number of cells on the longest axis of bounding box. e.g 200 + meshCells int // number of cells on the longest axis of bounding box. e.g 200 + order Order // + shape Shape // } // NewMarchingCubesFEUniform returns a RenderHex8 object. -func NewMarchingCubesFEUniform(meshCells int) *MarchingCubesFEUniform { +func NewMarchingCubesFEUniform(meshCells int, order Order, shape Shape) *MarchingCubesFEUniform { return &MarchingCubesFEUniform{ meshCells: meshCells, + order: order, + shape: shape, } } @@ -51,8 +76,8 @@ func (r *MarchingCubesFEUniform) LayerCounts(s sdf.SDF3) (int, int, int) { } // Render produces a finite elements mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of tetrahedra. -func (r *MarchingCubesFEUniform) RenderTet4(s sdf.SDF3, output chan<- []*Tet4) { +// Order and shape of finite elements are selectable. +func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output chan<- []*Fe) { // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() @@ -61,49 +86,42 @@ func (r *MarchingCubesFEUniform) RenderTet4(s sdf.SDF3, output chan<- []*Tet4) { bb1Size = bb1Size.Ceil().AddScalar(1) bb1Size = bb1Size.MulScalar(meshInc) bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingCubesTet4(s, bb, meshInc) -} - -// Render produces a finite elements mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of tetrahedra. -func (r *MarchingCubesFEUniform) RenderTet10(s sdf.SDF3, output chan<- []*Tet10) { - // work out the region we will sample - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - bb1Size = bb1Size.MulScalar(meshInc) - bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingCubesTet10(s, bb, meshInc) -} - -// Render produces a finite elements mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of hexahedra. -func (r *MarchingCubesFEUniform) RenderHex8(s sdf.SDF3, output chan<- []*Hex8) { - // work out the region we will sample - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - bb1Size = bb1Size.MulScalar(meshInc) - bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingCubesHex8(s, bb, meshInc) -} - -// Render produces a finite elements mesh over the bounding volume of an sdf3. -// Finite elements are in the shape of hexahedra. -func (r *MarchingCubesFEUniform) RenderHex20(s sdf.SDF3, output chan<- []*Hex20) { - // work out the region we will sample - bb0 := s.BoundingBox() - bb0Size := bb0.Size() - meshInc := bb0Size.MaxComponent() / float64(r.meshCells) - bb1Size := bb0Size.DivScalar(meshInc) - bb1Size = bb1Size.Ceil().AddScalar(1) - bb1Size = bb1Size.MulScalar(meshInc) - bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingCubesHex20(s, bb, meshInc) + switch r.order { + case Linear: + { + switch r.shape { + case Hexahedral: + { + output <- marchingCubesHex8(s, bb, meshInc) + } + case Tetrahedral: + { + output <- marchingCubesTet4(s, bb, meshInc) + } + case Both: + { + output <- marchingCubesHex8Tet4(s, bb, meshInc) + } + } + } + case Quadratic: + { + switch r.shape { + case Hexahedral: + { + output <- marchingCubesHex20(s, bb, meshInc) + } + case Tetrahedral: + { + output <- marchingCubesTet10(s, bb, meshInc) + } + case Both: + { + output <- marchingCubesHex20Tet10(s, bb, meshInc) + } + } + } + } } //----------------------------------------------------------------------------- @@ -187,6 +205,25 @@ func (l *layerXY) Get(x, y, z int) float64 { //----------------------------------------------------------------------------- +// Specify the point to create the tetrahedra. +// Point can be on edges or corners. +// Index from 0 to 11 means an edge. +// Index from 12 to 19 means a corner. +// Corners were originally indexed from 0 to 7 but they are shifted by 12. +// So, corners are from 0+12 to 7+12 i.e. from 12 to 19. +func point(edges [12]v3.Vec, corners [8]v3.Vec, index int) v3.Vec { + if 0 <= index && index < 12 { + return edges[index] + } else if index < 20 { + return corners[index-12] + } else { + // Should never reach here. + return v3.Vec{} + } +} + +//----------------------------------------------------------------------------- + // MATHEMATICA script is available here: // https://math.stackexchange.com/a/4709610/197913 func almostFlat(a, b, c, d v3.Vec) (bool, float64) { @@ -458,3 +495,2472 @@ func degenerateTriangles(a, b, c, d v3.Vec) bool { } //----------------------------------------------------------------------------- + +// Specify the edges & corners used to create the tetrahedra. +// Keep the index from 0 to 11 for edges, +// but shift the index for corners. +// Corners were originally indexed from 0 to 7. +// So, corners would be indexed from 0+12 to 7+12 i.e. from 12 to 19. +// Manually created by: +// https://github.com/Megidd/tetrahedron-table +var mcTetrahedronTable = [256][]int{ + // 0b00000000 case 0: no cube corner has zero/negative value. + {}, + // 0b00000001 case 1: first cube corner has zero/negative value. + {12, 0, 3, 8}, + // 0b00000010 case 2 + {13, 1, 0, 9}, + // 0b00000011 case 3 + { + 12, 13, 3, 8, + 13, 1, 3, 8, + 13, 1, 8, 9, + }, + // 0b00000100 case 4 + {14, 2, 1, 10}, + // 0b00000101 case 5 + { + 12, 0, 3, 8, + 14, 2, 1, 10, + }, + // 0b00000110 case 6 + { + 13, 14, 0, 9, + 14, 2, 0, 9, + 14, 2, 9, 10, + }, + // 0b00000111 case 7 + { + 12, 13, 3, 8, + 13, 2, 3, 8, + 13, 14, 2, 8, + 14, 2, 8, 10, + 13, 14, 8, 10, + 13, 10, 8, 9, + }, + // 0b00001000 case 8 + { + 15, 3, 2, 11, + }, + // 0b00001001 case 9 + { + 12, 0, 2, 11, + 12, 2, 15, 11, + 12, 0, 11, 8, + }, + // 0b00001010 case 10 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + }, + // 0b00001011 case 11 + { + 15, 12, 2, 11, + 12, 1, 2, 11, + 12, 13, 1, 11, + 13, 1, 11, 9, + 12, 13, 11, 9, + 11, 12, 9, 8, + }, + // 0b00001100 case 12 + { + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00001101 case 13 + { + 12, 0, 1, 8, + 12, 1, 14, 8, + 1, 14, 8, 10, + 14, 15, 12, 8, + 14, 15, 8, 10, + 10, 15, 8, 11, + }, + // 0b00001110 case 14 + { + 0, 15, 3, 11, + 0, 14, 15, 11, + 0, 14, 11, 9, + 0, 13, 14, 9, + 14, 11, 9, 10, + }, + // 0b00001111 case 15 + { + 12, 13, 14, 10, + 12, 13, 10, 9, + 12, 9, 10, 8, + 12, 14, 15, 8, + 14, 15, 8, 10, + 15, 8, 10, 11, + }, + // 0b00010000 case 16 + {8, 4, 7, 16}, + // 0b00010001 case 17 + { + 12, 0, 3, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b00010010 case 18 + { + 8, 4, 7, 16, + 13, 1, 0, 9, + }, + // 0b00010011 case 19 + { + 3, 12, 1, 7, + 12, 13, 1, 7, + 12, 13, 7, 16, + 13, 1, 7, 9, + 13, 7, 16, 9, + 16, 9, 7, 4, + }, + // 0b00010100 case 20 + { + 8, 4, 7, 16, + 1, 14, 2, 10, + }, + // 0b00010101 case 21 + { + 1, 14, 2, 10, + 3, 12, 0, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b00010110 case 22 + { + 8, 4, 7, 16, + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 10, + }, + // 0b00010111 case 23 + { + 3, 12, 2, 7, + 12, 13, 2, 7, + 13, 2, 7, 4, + 13, 2, 4, 9, + 12, 13, 7, 16, + 16, 13, 7, 4, + 13, 14, 2, 9, + 14, 2, 9, 10, + }, + // 0b00011000 case 24 + { + 8, 4, 7, 16, + 2, 15, 3, 11, + }, + // 0b00011001 case 25 + { + 12, 0, 2, 4, + 12, 2, 15, 4, + 2, 15, 4, 11, + 12, 4, 15, 11, + 12, 4, 11, 7, + 12, 4, 7, 16, + }, + // 0b00011010 case 26 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + 8, 4, 7, 16, + }, + // 0b00011011 case 27 + { + 12, 2, 15, 11, + 12, 1, 2, 11, + 12, 13, 1, 11, + 13, 1, 11, 9, + 12, 13, 11, 9, + 12, 9, 11, 4, + 12, 4, 11, 16, + 11, 16, 4, 7, + }, + // 0b00011100 case 28 + { + 8, 4, 7, 16, + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00011101 case 29 + { + 1, 14, 15, 10, + 15, 1, 10, 11, + 12, 1, 15, 11, + 12, 0, 1, 4, + 12, 1, 11, 4, + 12, 4, 11, 7, + 12, 4, 7, 16, + }, + // 0b00011110 case 30 + { + 8, 4, 7, 16, + 13, 14, 0, 9, + 14, 3, 0, 9, + 14, 15, 3, 9, + 15, 3, 9, 11, + 14, 15, 9, 11, + 14, 11, 9, 10, + }, + // 0b00011111 case 31 + { + 13, 14, 15, 11, + 13, 14, 11, 9, + 14, 11, 9, 10, + 12, 13, 15, 9, + 12, 9, 15, 11, + 12, 9, 11, 7, + 12, 9, 7, 16, + 16, 9, 7, 4, + }, + // 0b00100000 case 32 + {9, 5, 4, 17}, + // 0b00100001 case 33 + { + 12, 0, 3, 8, + 9, 5, 4, 17, + }, + // 0b00100010 case 34 + { + 0, 13, 1, 5, + 0, 13, 5, 4, + 4, 13, 5, 17, + }, + // 0b00100011 case 35 + { + 13, 1, 3, 5, + 13, 3, 12, 5, + 12, 5, 3, 4, + 12, 4, 3, 8, + 12, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00100100 case 36 + { + 1, 14, 2, 10, + 9, 5, 4, 17, + }, + // 0b00100101 case 37 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 4, 9, 5, 17, + }, + // 0b00100110 case 38 + { + 0, 14, 2, 4, + 14, 2, 4, 5, + 14, 2, 5, 10, + 0, 13, 14, 4, + 13, 14, 4, 5, + 13, 5, 4, 17, + }, + // 0b00100111 case 39 + { + 13, 14, 2, 10, + 12, 13, 2, 10, + 12, 2, 3, 10, + 12, 10, 3, 8, + 12, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 4, + 13, 5, 4, 17, + }, + // 0b00101000 case 40 + { + 9, 5, 4, 17, + 2, 15, 3, 11, + }, + // 0b00101001 case 41 + { + 9, 5, 4, 17, + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + }, + // 0b00101010 case 42 + { + 2, 15, 3, 11, + 0, 13, 1, 4, + 4, 13, 1, 5, + 4, 13, 5, 17, + }, + // 0b00101011 case 43 + { + 2, 15, 12, 11, + 11, 12, 2, 8, + 12, 1, 2, 8, + 12, 13, 1, 8, + 8, 1, 2, 5, + 13, 1, 8, 5, + 8, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00101100 case 44 + { + 9, 5, 4, 17, + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00101101 case 45 + { + 9, 5, 4, 17, + 1, 14, 0, 10, + 14, 12, 0, 10, + 12, 0, 10, 8, + 14, 15, 12, 10, + 15, 12, 10, 8, + 15, 8, 10, 11, + }, + // 0b00101110 case 46 + { + 14, 15, 3, 11, + 14, 3, 0, 11, + 0, 14, 11, 5, + 14, 11, 5, 10, + 0, 13, 14, 5, + 0, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00101111 case 47 + { + 14, 15, 12, 8, + 14, 15, 8, 10, + 15, 8, 10, 11, + 12, 13, 14, 10, + 12, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 4, + 13, 5, 4, 17, + }, + // 0b00110000 case 48 + { + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + }, + // 0b00110001 case 49 + { + 3, 12, 0, 5, + 3, 12, 5, 7, + 12, 0, 7, 16, + 0, 5, 7, 16, + 0, 5, 16, 9, + 9, 5, 16, 17, + }, + // 0b00110010 case 50 + { + 0, 13, 1, 7, + 13, 1, 7, 5, + 0, 13, 5, 17, + 0, 5, 7, 17, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b00110011 case 51 + { + 12, 1, 3, 5, + 3, 12, 5, 7, + 12, 13, 1, 5, + 12, 13, 5, 17, + 12, 17, 5, 7, + 12, 17, 7, 16, + }, + // 0b00110100 case 52 + { + 1, 14, 2, 10, + 7, 8, 5, 16, + 8, 9, 5, 16, + 16, 9, 5, 17, + }, + // 0b00110101 case 53 + { + 1, 14, 2, 10, + 3, 12, 0, 5, + 3, 12, 5, 7, + 0, 9, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 12, + 12, 17, 7, 16, + }, + // 0b00110110 case 54 + { + 13, 14, 2, 10, + 0, 13, 2, 10, + 0, 10, 2, 8, + 0, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 17, + 8, 17, 5, 7, + 8, 17, 7, 16, + }, + // 0b00110111 case 55 + { + 13, 14, 2, 10, + 13, 2, 3, 10, + 13, 10, 3, 5, + 12, 13, 3, 5, + 12, 13, 5, 17, + 3, 12, 5, 7, + 12, 17, 5, 7, + 12, 17, 7, 16, + }, + // 0b00111000 case 56 + { + 15, 3, 2, 11, + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + }, + // 0b00111001 case 57 + { + 12, 0, 2, 9, + 15, 12, 2, 9, + 2, 15, 9, 11, + 15, 12, 9, 11, + 12, 9, 11, 7, + 12, 9, 7, 16, + 9, 7, 16, 5, + 9, 5, 16, 17, + }, + // 0b00111010 case 58 + { + 15, 3, 2, 11, + 0, 13, 1, 8, + 13, 1, 8, 7, + 13, 1, 7, 5, + 13, 7, 8, 16, + 13, 7, 16, 5, + 13, 5, 16, 17, + }, + // 0b00111011 case 59 + { + 12, 13, 1, 17, + 12, 17, 1, 5, + 12, 5, 1, 7, + 12, 17, 5, 7, + 12, 17, 7, 16, + 2, 12, 1, 7, + 15, 12, 2, 7, + 15, 7, 2, 11, + }, + // 0b00111100 case 60 + { + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + 14, 3, 1, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00111101 case 61 + { + 0, 9, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 16, + 0, 16, 7, 12, + 12, 0, 11, 7, + 14, 0, 1, 10, + 12, 0, 15, 11, + 14, 15, 0, 11, + 14, 11, 0, 10, + }, + // 0b00111110 case 62 + { + 15, 3, 0, 11, + 14, 15, 0, 11, + 14, 11, 0, 10, + 14, 0, 13, 10, + 0, 13, 10, 5, + 0, 13, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b00111111 case 63 + { + 12, 14, 15, 11, + 12, 14, 11, 10, + 12, 13, 14, 10, + 11, 12, 10, 7, + 12, 13, 10, 7, + 12, 13, 7, 16, + 13, 10, 7, 5, + 13, 5, 7, 17, + 13, 7, 16, 17, + }, + // 0b01000000 case 64 + {10, 6, 5, 18}, + // 0b01000001 case 65 + { + 12, 0, 3, 8, + 10, 6, 5, 18, + }, + // 0b01000010 case 66 + { + 0, 13, 1, 9, + 10, 6, 5, 18, + }, + // 0b01000011 case 67 + { + 10, 6, 5, 18, + 3, 12, 1, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + }, + // 0b01000100 case 68 + { + 1, 14, 2, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01000101 case 69 + { + 12, 0, 3, 8, + 14, 2, 1, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01000110 case 70 + { + 0, 13, 2, 6, + 0, 13, 6, 9, + 13, 14, 2, 6, + 13, 14, 6, 9, + 9, 14, 6, 5, + 14, 6, 5, 18, + }, + // 0b01000111 case 71 + { + 3, 12, 2, 8, + 12, 13, 2, 8, + 13, 2, 8, 9, + 13, 14, 2, 9, + 9, 2, 8, 5, + 9, 14, 2, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01001000 case 72 + { + 10, 6, 5, 18, + 15, 3, 2, 11, + }, + // 0b01001001 case 73 + { + 10, 6, 5, 18, + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + }, + // 0b01001010 case 74 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + 10, 6, 5, 18, + }, + // 0b01001011 case 75 + { + 10, 6, 5, 18, + 2, 15, 1, 11, + 15, 13, 1, 11, + 13, 1, 11, 9, + 15, 12, 13, 11, + 11, 12, 13, 9, + 11, 12, 9, 8, + }, + // 0b01001100 case 76 + { + 14, 15, 3, 11, + 1, 14, 3, 11, + 1, 11, 3, 5, + 1, 14, 11, 5, + 5, 14, 11, 6, + 5, 14, 6, 18, + }, + // 0b01001101 case 77 + { + 12, 0, 15, 8, + 15, 8, 0, 11, + 14, 0, 1, 5, + 14, 15, 0, 11, + 14, 0, 5, 6, + 14, 11, 0, 6, + 14, 6, 5, 18, + }, + // 0b01001110 case 78 + { + 0, 13, 14, 9, + 14, 15, 3, 11, + 14, 3, 0, 9, + 14, 11, 3, 6, + 14, 3, 9, 5, + 14, 6, 3, 5, + 14, 6, 5, 18, + }, + // 0b01001111 case 79 + { + 15, 12, 13, 8, + 13, 15, 8, 11, + 13, 11, 8, 9, + 13, 14, 15, 9, + 14, 15, 9, 11, + 9, 14, 11, 5, + 14, 11, 5, 6, + 14, 6, 5, 18, + }, + // 0b01010000 case 80 + { + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01010001 case 81 + { + 10, 6, 5, 18, + 12, 0, 3, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b01010010 case 82 + { + 13, 1, 0, 9, + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01010011 case 83 + { + 10, 6, 5, 18, + 12, 13, 1, 9, + 3, 12, 1, 9, + 3, 9, 1, 7, + 3, 12, 9, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + }, + // 0b01010100 case 84 + { + 8, 4, 7, 16, + 14, 2, 1, 6, + 1, 14, 6, 5, + 5, 14, 6, 18, + }, + // 0b01010101 case 85 + { + 3, 12, 0, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + 1, 14, 2, 5, + 14, 2, 5, 6, + 5, 14, 6, 18, + }, + // 0b01010110 case 86 + { + 8, 4, 7, 16, + 0, 13, 2, 6, + 0, 13, 6, 9, + 13, 14, 2, 6, + 13, 14, 6, 9, + 14, 6, 9, 5, + 14, 6, 5, 18, + }, + // 0b01010111 case 87 + { + 13, 2, 3, 9, + 13, 3, 12, 9, + 13, 14, 2, 9, + 14, 2, 9, 6, + 3, 12, 9, 7, + 12, 9, 7, 4, + 14, 6, 9, 5, + 12, 4, 7, 16, + 14, 6, 5, 18, + }, + // 0b01011000 case 88 + { + 8, 4, 7, 16, + 10, 6, 5, 18, + 15, 3, 2, 11, + }, + // 0b01011001 case 89 + { + 10, 6, 5, 18, + 2, 15, 0, 4, + 2, 15, 4, 11, + 15, 12, 0, 4, + 15, 12, 4, 11, + 11, 12, 4, 7, + 7, 12, 4, 16, + }, + // 0b01011010 case 90 + { + 13, 1, 0, 9, + 2, 15, 3, 11, + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01011011 case 91 + { + 10, 6, 5, 18, + 15, 1, 2, 11, + 15, 13, 1, 11, + 13, 1, 11, 9, + 15, 12, 13, 11, + 12, 13, 11, 9, + 12, 9, 11, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + }, + // 0b01011100 case 92 + { + 8, 4, 7, 16, + 1, 15, 3, 5, + 15, 3, 5, 6, + 15, 3, 6, 11, + 1, 14, 15, 6, + 1, 14, 6, 5, + 14, 6, 5, 18, + }, + // 0b01011101 case 93 + { + 15, 0, 1, 11, + 15, 12, 0, 11, + 1, 14, 15, 11, + 11, 12, 0, 4, + 11, 1, 14, 5, + 11, 12, 4, 7, + 11, 5, 14, 6, + 14, 6, 5, 18, + 12, 4, 7, 16, + }, + // 0b01011110 case 94 + { + 8, 4, 7, 16, + 13, 3, 0, 9, + 13, 15, 3, 9, + 15, 3, 9, 11, + 13, 14, 15, 9, + 14, 15, 9, 11, + 14, 11, 9, 5, + 14, 11, 5, 6, + 14, 6, 5, 18, + }, + // 0b01011111 case 95 + { + 15, 12, 13, 11, + 11, 12, 13, 9, + 11, 12, 9, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + 13, 14, 15, 9, + 14, 15, 9, 11, + 9, 14, 11, 5, + 5, 14, 11, 6, + 14, 6, 5, 18, + }, + // 0b01100000 case 96 + { + 9, 10, 4, 17, + 10, 6, 4, 17, + 10, 6, 17, 18, + }, + // 0b01100001 case 97 + { + 12, 0, 3, 8, + 4, 9, 6, 17, + 9, 10, 6, 17, + 17, 10, 6, 18, + }, + // 0b01100010 case 98 + { + 0, 13, 1, 6, + 1, 10, 6, 18, + 13, 1, 6, 18, + 0, 13, 6, 4, + 13, 18, 6, 4, + 13, 18, 4, 17, + }, + // 0b01100011 case 99 + { + 3, 12, 1, 8, + 12, 13, 1, 8, + 8, 13, 1, 17, + 1, 8, 17, 4, + 1, 6, 8, 4, + 1, 4, 17, 6, + 1, 6, 17, 10, + 17, 10, 6, 18, + }, + // 0b01100100 case 100 + { + 1, 14, 2, 6, + 1, 2, 4, 6, + 1, 14, 6, 18, + 1, 18, 6, 4, + 1, 18, 4, 9, + 9, 18, 4, 17, + }, + // 0b01100101 case 101 + { + 3, 12, 0, 8, + 1, 14, 2, 9, + 9, 14, 2, 4, + 14, 2, 4, 6, + 9, 14, 4, 17, + 14, 6, 4, 17, + 14, 6, 17, 18, + }, + // 0b01100110 case 102 + { + 0, 13, 2, 4, + 13, 14, 2, 4, + 14, 2, 4, 6, + 14, 18, 6, 4, + 14, 18, 4, 13, + 13, 18, 4, 17, + }, + // 0b01100111 case 103 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 13, 14, 2, 8, + 14, 2, 8, 4, + 13, 14, 8, 4, + 14, 2, 4, 6, + 13, 14, 4, 17, + 14, 4, 17, 6, + 14, 6, 17, 18, + }, + // 0b01101000 case 104 + { + 2, 15, 3, 11, + 4, 9, 6, 17, + 9, 10, 6, 17, + 10, 6, 17, 18, + }, + // 0b01101001 case 105 + { + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + 4, 9, 6, 17, + 9, 10, 6, 17, + 10, 6, 17, 18, + }, + // 0b01101010 case 106 + { + 2, 15, 3, 11, + 0, 13, 1, 6, + 0, 13, 6, 4, + 1, 10, 6, 4, + 13, 1, 4, 17, + 10, 6, 4, 18, + 17, 1, 4, 10, + 17, 10, 4, 18, + }, + // 0b01101011 case 107 + { + 15, 1, 2, 11, + 15, 12, 1, 11, + 12, 1, 11, 8, + 12, 13, 1, 8, + 8, 13, 1, 4, + 13, 1, 4, 17, + 1, 6, 4, 17, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01101100 case 108 + { + 1, 14, 3, 9, + 14, 15, 3, 9, + 15, 3, 9, 11, + 14, 15, 9, 11, + 14, 11, 9, 6, + 14, 6, 9, 18, + 9, 18, 6, 4, + 4, 9, 18, 17, + }, + // 0b01101101 case 109 + { + 12, 0, 1, 8, + 15, 12, 1, 8, + 15, 8, 1, 11, + 14, 15, 1, 11, + 1, 14, 11, 6, + 1, 14, 6, 18, + 1, 18, 6, 4, + 1, 18, 4, 17, + 1, 17, 4, 9, + }, + // 0b01101110 case 110 + { + 14, 15, 3, 11, + 0, 14, 3, 11, + 0, 13, 14, 11, + 0, 13, 11, 6, + 13, 14, 11, 6, + 13, 14, 6, 18, + 0, 13, 6, 4, + 13, 18, 6, 4, + 13, 18, 4, 17, + }, + // 0b01101111 case 111 + { + 15, 12, 13, 11, + 13, 14, 15, 11, + 12, 13, 11, 8, + 8, 13, 14, 4, + 14, 8, 4, 11, + 14, 11, 4, 6, + 13, 14, 4, 17, + 14, 4, 17, 6, + 14, 6, 17, 18, + }, + // 0b01110000 case 112 + { + 8, 9, 10, 7, + 9, 10, 7, 6, + 8, 9, 7, 16, + 9, 10, 6, 18, + 9, 7, 16, 17, + 9, 6, 7, 17, + 9, 18, 6, 17, + }, + // 0b01110001 case 113 + { + 12, 0, 3, 7, + 12, 0, 7, 16, + 0, 9, 10, 7, + 0, 9, 7, 16, + 9, 10, 16, 17, + 10, 7, 16, 17, + 10, 7, 17, 6, + 10, 6, 17, 18, + }, + // 0b01110010 case 114 + { + 0, 13, 1, 10, + 0, 13, 10, 8, + 13, 10, 8, 6, + 13, 6, 8, 7, + 13, 10, 6, 18, + 13, 7, 8, 16, + 13, 6, 7, 17, + 13, 18, 6, 17, + 13, 7, 16, 17, + }, + // 0b01110011 case 115 + { + 3, 12, 13, 7, + 12, 13, 7, 16, + 13, 1, 3, 7, + 13, 1, 16, 17, + 1, 7, 16, 6, + 1, 6, 16, 17, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01110100 case 116 + { + 1, 14, 2, 6, + 1, 14, 6, 18, + 1, 18, 6, 7, + 1, 8, 9, 16, + 1, 7, 8, 16, + 1, 18, 7, 16, + 1, 18, 16, 9, + 9, 18, 16, 17, + }, + // 0b01110101 case 117 + { + 3, 12, 0, 9, + 3, 12, 9, 7, + 12, 9, 7, 16, + 9, 7, 16, 17, + 9, 6, 7, 17, + 1, 14, 2, 9, + 14, 2, 9, 6, + 14, 6, 9, 17, + 14, 6, 17, 18, + }, + // 0b01110110 case 118 + { + 13, 14, 2, 6, + 0, 13, 2, 6, + 13, 14, 6, 18, + 0, 13, 18, 17, + 0, 17, 18, 6, + 0, 17, 6, 7, + 0, 17, 7, 16, + 0, 7, 8, 16, + }, + // 0b01110111 case 119 + { + 12, 2, 3, 7, + 12, 14, 2, 7, + 14, 2, 7, 6, + 12, 13, 14, 7, + 12, 13, 7, 16, + 14, 6, 7, 18, + 14, 18, 7, 16, + 13, 14, 16, 18, + 13, 18, 16, 17, + }, + // 0b01111000 case 120 + { + 2, 15, 3, 11, + 8, 9, 10, 7, + 9, 10, 7, 6, + 9, 10, 6, 18, + 8, 9, 7, 16, + 9, 18, 6, 17, + 9, 6, 7, 17, + 9, 7, 16, 17, + }, + // 0b01111001 case 121 + { + 15, 0, 2, 7, + 15, 7, 2, 11, + 15, 12, 0, 7, + 12, 0, 7, 16, + 16, 0, 7, 9, + 16, 9, 7, 17, + 9, 10, 7, 17, + 10, 7, 17, 18, + 10, 7, 18, 6, + }, + // 0b01111010 case 122 + { + 15, 3, 2, 11, + 0, 13, 1, 10, + 0, 13, 10, 8, + 13, 10, 8, 6, + 8, 13, 6, 7, + 13, 6, 7, 17, + 13, 10, 6, 17, + 13, 7, 8, 17, + 17, 10, 6, 18, + 17, 7, 8, 16, + }, + // 0b01111011 case 123 + { + 15, 1, 2, 11, + 15, 12, 1, 11, + 12, 13, 1, 11, + 13, 1, 11, 7, + 12, 13, 11, 7, + 12, 13, 7, 16, + 13, 7, 16, 17, + 13, 1, 7, 17, + 1, 7, 17, 6, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01111100 case 124 + { + 3, 11, 6, 15, + 1, 15, 3, 6, + 1, 14, 15, 6, + 1, 14, 6, 18, + 1, 18, 6, 9, + 9, 18, 6, 17, + 8, 9, 6, 17, + 8, 17, 6, 7, + 8, 17, 7, 16, + }, + // 0b01111101 case 125 + { + 12, 0, 1, 9, + 12, 1, 14, 9, + 12, 14, 15, 9, + 12, 9, 15, 17, + 14, 15, 9, 17, + 15, 12, 17, 16, + 15, 17, 14, 18, + 15, 16, 17, 7, + 15, 17, 18, 6, + 15, 7, 17, 11, + 15, 17, 6, 11, + 11, 6, 7, 17, + }, + // 0b01111110 case 126 + { + 15, 3, 0, 11, + 14, 15, 0, 11, + 0, 14, 11, 6, + 0, 13, 14, 6, + 13, 14, 6, 18, + 0, 13, 18, 17, + 0, 18, 6, 17, + 0, 17, 6, 7, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b01111111 case 127 + { + 6, 7, 11, 15, + 12, 13, 15, 7, + 13, 14, 15, 7, + 14, 15, 7, 6, + 13, 14, 7, 6, + 13, 14, 6, 18, + 12, 13, 7, 16, + 13, 18, 6, 17, + 13, 6, 7, 17, + 13, 7, 16, 17, + }, + // 0b10000000 case 128 + { + 11, 7, 6, 19, + }, + // 0b10000001 case 129 + { + 3, 12, 0, 8, + 11, 7, 6, 19, + }, + // 0b10000010 case 130 + { + 0, 13, 1, 9, + 11, 7, 6, 19, + }, + // 0b10000011 case 131 + { + 11, 7, 6, 19, + 3, 12, 1, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + }, + // 0b10000100 case 132 + { + 1, 14, 2, 10, + 11, 7, 6, 19, + }, + // 0b10000101 case 133 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 11, 7, 6, 19, + }, + // 0b10000110 case 134 + { + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 10, + 11, 7, 6, 19, + }, + // 0b10000111 case 135 + { + 12, 2, 3, 8, + 12, 14, 2, 8, + 14, 2, 8, 10, + 12, 13, 14, 8, + 13, 14, 8, 10, + 13, 10, 8, 9, + 11, 7, 6, 19, + }, + // 0b10001000 case 136 + { + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001001 case 137 + { + 2, 15, 0, 6, + 15, 12, 0, 6, + 12, 0, 6, 7, + 12, 0, 7, 8, + 15, 12, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001010 case 138 + { + 0, 13, 1, 9, + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001011 case 139 + { + 12, 13, 1, 9, + 12, 9, 1, 8, + 12, 1, 2, 8, + 2, 8, 1, 7, + 2, 7, 1, 6, + 2, 15, 12, 8, + 2, 15, 8, 7, + 2, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10001100 case 140 + { + 15, 3, 1, 7, + 14, 15, 1, 7, + 1, 14, 7, 6, + 1, 14, 6, 10, + 14, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10001101 case 141 + { + 14, 0, 1, 10, + 14, 12, 0, 10, + 12, 0, 10, 8, + 14, 15, 12, 10, + 15, 12, 10, 8, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + }, + // 0b10001110 case 142 + { + 0, 13, 14, 9, + 14, 0, 9, 10, + 14, 15, 0, 10, + 15, 3, 0, 10, + 10, 3, 0, 7, + 10, 15, 3, 7, + 10, 15, 7, 6, + 6, 15, 7, 19, + }, + // 0b10001111 case 143 + { + 14, 15, 12, 8, + 14, 15, 8, 10, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + 12, 13, 14, 10, + 12, 13, 10, 8, + 8, 13, 10, 9, + }, + // 0b10010000 case 144 + { + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010001 case 145 + { + 3, 12, 0, 4, + 3, 4, 0, 6, + 12, 4, 6, 16, + 3, 12, 6, 16, + 3, 16, 6, 19, + 3, 19, 6, 11, + }, + // 0b10010010 case 146 + { + 0, 13, 1, 9, + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010011 case 147 + { + 3, 13, 1, 9, + 3, 12, 13, 9, + 3, 12, 9, 6, + 12, 9, 6, 4, + 3, 12, 4, 16, + 3, 16, 4, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10010100 case 148 + { + 1, 14, 2, 10, + 11, 8, 6, 19, + 8, 4, 6, 19, + 8, 4, 19, 16, + }, + // 0b10010101 case 149 + { + 1, 14, 2, 10, + 3, 12, 0, 11, + 12, 0, 11, 6, + 12, 6, 11, 19, + 0, 6, 19, 4, + 12, 0, 19, 4, + 12, 4, 19, 16, + }, + // 0b10010110 case 150 + { + 13, 14, 0, 9, + 14, 2, 0, 9, + 14, 2, 9, 10, + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010111 case 151 + { + 3, 14, 2, 10, + 3, 13, 14, 10, + 3, 13, 10, 9, + 3, 12, 13, 9, + 3, 12, 9, 4, + 3, 12, 4, 16, + 3, 16, 4, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10011000 case 152 + { + 2, 15, 3, 8, + 2, 15, 8, 4, + 15, 8, 4, 16, + 2, 15, 4, 6, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011001 case 153 + { + 12, 0, 2, 4, + 15, 12, 2, 4, + 2, 15, 4, 6, + 12, 4, 15, 16, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011010 case 154 + { + 0, 13, 1, 9, + 2, 15, 3, 8, + 2, 15, 8, 4, + 15, 8, 4, 16, + 2, 15, 4, 6, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011011 case 155 + { + 2, 13, 1, 9, + 2, 13, 9, 4, + 12, 13, 2, 4, + 15, 12, 2, 4, + 2, 15, 4, 6, + 15, 12, 4, 16, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011100 case 156 + { + 14, 3, 1, 8, + 14, 8, 1, 10, + 14, 15, 3, 8, + 14, 15, 8, 10, + 10, 15, 8, 6, + 15, 8, 6, 19, + 6, 19, 8, 4, + 19, 8, 4, 16, + }, + // 0b10011101 case 157 + { + 14, 0, 1, 10, + 14, 15, 0, 10, + 15, 12, 0, 10, + 12, 0, 10, 6, + 15, 12, 10, 6, + 12, 0, 6, 4, + 15, 12, 6, 19, + 12, 4, 6, 19, + 12, 4, 19, 16, + }, + // 0b10011110 case 158 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 10, + 14, 15, 3, 10, + 15, 3, 10, 6, + 15, 3, 6, 19, + 3, 6, 19, 4, + 3, 4, 19, 8, + 8, 4, 19, 16, + }, + // 0b10011111 case 159 + { + 12, 13, 14, 10, + 12, 13, 10, 9, + 12, 14, 15, 10, + 15, 9, 10, 6, + 15, 12, 9, 6, + 12, 9, 6, 4, + 15, 12, 6, 19, + 12, 6, 19, 4, + 12, 4, 19, 16, + }, + // 0b10100000 case 160 + { + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100001 case 161 + { + 3, 12, 0, 8, + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100010 case 162 + { + 0, 13, 1, 4, + 13, 1, 4, 5, + 4, 13, 5, 17, + 11, 7, 6, 19, + }, + // 0b10100011 case 163 + { + 3, 13, 1, 5, + 3, 12, 13, 5, + 12, 13, 5, 17, + 3, 17, 5, 4, + 3, 12, 17, 4, + 3, 12, 4, 8, + 11, 7, 6, 19, + }, + // 0b10100100 case 164 + { + 1, 14, 2, 10, + 11, 7, 6, 19, + 9, 5, 4, 17, + }, + // 0b10100101 case 165 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100110 case 166 + { + 14, 2, 0, 10, + 13, 14, 0, 10, + 0, 13, 10, 5, + 0, 13, 5, 4, + 13, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100111 case 167 + { + 11, 7, 6, 19, + 3, 14, 2, 10, + 3, 12, 14, 10, + 3, 12, 10, 8, + 12, 13, 14, 10, + 12, 13, 10, 8, + 8, 13, 10, 5, + 8, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b10101000 case 168 + { + 9, 5, 4, 17, + 2, 15, 3, 6, + 15, 3, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101001 case 169 + { + 9, 5, 4, 17, + 2, 12, 0, 6, + 12, 0, 6, 7, + 12, 0, 7, 8, + 2, 15, 12, 6, + 15, 12, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101010 case 170 + { + 0, 13, 1, 4, + 13, 1, 4, 5, + 13, 5, 4, 17, + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10101011 case 171 + { + 2, 12, 1, 8, + 12, 13, 1, 8, + 2, 15, 12, 8, + 8, 13, 1, 5, + 8, 13, 5, 4, + 4, 13, 5, 17, + 2, 15, 8, 6, + 15, 8, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101100 case 172 + { + 9, 5, 4, 17, + 1, 15, 3, 7, + 1, 14, 15, 7, + 1, 14, 7, 6, + 1, 14, 6, 10, + 14, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10101101 case 173 + { + 9, 5, 4, 17, + 1, 12, 0, 8, + 14, 12, 1, 8, + 14, 15, 12, 8, + 14, 8, 1, 10, + 14, 15, 8, 10, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + }, + // 0b10101110 case 174 + { + 13, 14, 0, 10, + 14, 3, 0, 10, + 14, 15, 3, 10, + 0, 13, 10, 5, + 0, 5, 10, 4, + 0, 13, 5, 4, + 13, 5, 4, 17, + 15, 3, 10, 7, + 15, 7, 10, 6, + 15, 7, 6, 19, + }, + // 0b10101111 case 175 + { + 12, 13, 14, 10, + 12, 14, 15, 10, + 12, 13, 10, 8, + 10, 15, 12, 8, + 10, 15, 8, 6, + 15, 8, 6, 7, + 15, 7, 6, 19, + 13, 10, 8, 4, + 13, 10, 4, 5, + 13, 5, 4, 17, + }, + // 0b10110000 case 176 + { + 11, 8, 9, 5, + 11, 8, 5, 6, + 8, 9, 5, 17, + 8, 6, 11, 19, + 8, 17, 5, 16, + 8, 5, 6, 16, + 8, 6, 19, 16, + }, + // 0b10110001 case 177 + { + 12, 0, 3, 11, + 11, 12, 0, 9, + 11, 12, 9, 6, + 12, 9, 6, 5, + 12, 6, 11, 19, + 12, 9, 5, 17, + 12, 17, 5, 16, + 12, 5, 6, 16, + 12, 6, 19, 16, + }, + // 0b10110010 case 178 + { + 0, 13, 1, 5, + 0, 13, 5, 17, + 0, 17, 5, 6, + 0, 17, 6, 11, + 11, 17, 6, 19, + 0, 17, 11, 19, + 0, 19, 11, 8, + 0, 17, 19, 8, + 8, 17, 19, 16, + }, + // 0b10110011 case 179 + { + 3, 13, 1, 5, + 3, 12, 13, 5, + 12, 13, 5, 17, + 3, 12, 17, 16, + 3, 17, 5, 16, + 3, 16, 5, 6, + 3, 16, 6, 11, + 16, 6, 11, 19, + }, + // 0b10110100 case 180 + { + 11, 8, 9, 5, + 11, 8, 5, 6, + 8, 9, 5, 17, + 8, 17, 5, 16, + 8, 5, 6, 16, + 8, 6, 11, 19, + 8, 6, 19, 16, + 1, 14, 2, 10, + }, + // 0b10110101 case 181 + { + 1, 14, 2, 10, + 3, 12, 0, 9, + 3, 12, 9, 11, + 11, 12, 9, 5, + 11, 12, 5, 6, + 12, 9, 5, 17, + 11, 12, 6, 19, + 12, 17, 5, 16, + 12, 5, 6, 16, + 12, 6, 19, 16, + }, + // 0b10110110 case 182 + { + 13, 14, 2, 10, + 0, 13, 2, 10, + 0, 10, 2, 5, + 0, 13, 10, 5, + 0, 13, 5, 17, + 0, 17, 5, 8, + 8, 17, 5, 16, + 11, 8, 5, 16, + 11, 16, 5, 6, + 11, 16, 6, 19, + }, + // 0b10110111 case 183 + { + 3, 14, 2, 10, + 3, 13, 14, 10, + 3, 12, 13, 10, + 3, 12, 10, 5, + 12, 13, 10, 5, + 12, 13, 5, 17, + 3, 12, 17, 16, + 3, 17, 5, 16, + 3, 16, 5, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10111000 case 184 + { + 8, 9, 5, 17, + 8, 17, 5, 16, + 2, 15, 3, 8, + 2, 15, 8, 5, + 2, 15, 5, 6, + 15, 8, 5, 6, + 6, 8, 5, 16, + 6, 15, 8, 19, + 6, 19, 8, 16, + }, + // 0b10111001 case 185 + { + 2, 15, 0, 6, + 15, 12, 0, 6, + 15, 12, 6, 19, + 12, 0, 19, 16, + 0, 6, 19, 16, + 0, 6, 16, 5, + 0, 5, 16, 9, + 16, 9, 5, 17, + }, + // 0b10111010 case 186 + { + 0, 13, 1, 8, + 13, 1, 8, 5, + 8, 13, 5, 17, + 8, 17, 5, 16, + 8, 16, 5, 6, + 2, 15, 3, 8, + 2, 15, 8, 6, + 15, 8, 6, 16, + 15, 16, 6, 19, + }, + // 0b10111011 case 187 + { + 2, 13, 1, 5, + 2, 12, 13, 5, + 12, 13, 5, 17, + 12, 17, 5, 16, + 12, 2, 15, 5, + 2, 15, 5, 6, + 15, 12, 5, 16, + 15, 16, 5, 6, + 15, 16, 6, 19, + }, + // 0b10111100 case 188 + { + 14, 3, 1, 6, + 1, 14, 6, 10, + 14, 15, 3, 6, + 15, 3, 6, 19, + 3, 6, 19, 8, + 8, 6, 19, 16, + 8, 6, 16, 9, + 9, 6, 16, 5, + 9, 5, 16, 17, + }, + // 0b10111101 case 189 + { + 14, 0, 1, 10, + 14, 12, 0, 10, + 14, 15, 12, 10, + 12, 0, 10, 6, + 10, 15, 12, 6, + 6, 15, 12, 19, + 12, 0, 19, 16, + 0, 6, 19, 16, + 0, 6, 16, 5, + 0, 5, 16, 9, + 16, 9, 5, 17, + }, + // 0b10111110 case 190 + { + 0, 15, 3, 8, + 0, 14, 15, 8, + 0, 13, 14, 8, + 8, 14, 15, 16, + 14, 15, 16, 19, + 13, 14, 8, 16, + 13, 14, 16, 17, + 14, 16, 17, 5, + 14, 16, 5, 10, + 10, 16, 5, 6, + 14, 19, 16, 10, + 10, 19, 16, 6, + }, + // 0b10111111 case 191 + { + 13, 15, 12, 16, + 13, 14, 15, 16, + 13, 14, 16, 17, + 14, 15, 16, 19, + 14, 16, 17, 5, + 14, 19, 16, 6, + 14, 6, 16, 10, + 14, 16, 5, 10, + 10, 6, 16, 5, + }, + // 0b11000000 case 192 + { + 10, 11, 5, 18, + 18, 11, 5, 7, + 11, 7, 18, 19, + }, + // 0b11000001 case 193 + { + 3, 12, 0, 8, + 5, 10, 11, 18, + 5, 18, 11, 7, + 11, 7, 18, 19, + }, + // 0b11000010 case 194 + { + 0, 13, 1, 9, + 10, 11, 5, 18, + 11, 7, 5, 18, + 11, 7, 18, 19, + }, + // 0b11000011 case 195 + { + 12, 1, 3, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + 10, 11, 5, 18, + 11, 7, 5, 18, + 11, 7, 18, 19, + }, + // 0b11000100 case 196 + { + 1, 14, 2, 7, + 1, 14, 7, 5, + 14, 2, 5, 18, + 2, 7, 5, 18, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11000101 case 197 + { + 1, 14, 2, 7, + 1, 14, 7, 5, + 14, 2, 5, 18, + 2, 7, 5, 18, + 2, 7, 18, 11, + 11, 7, 18, 19, + 3, 12, 0, 8, + }, + // 0b11000110 case 198 + { + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 5, + 14, 2, 5, 18, + 2, 9, 5, 7, + 2, 5, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11000111 case 199 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 8, 13, 2, 9, + 13, 14, 2, 9, + 9, 14, 2, 5, + 14, 2, 5, 18, + 2, 5, 18, 7, + 7, 18, 2, 11, + 18, 11, 7, 19, + }, + // 0b11001000 case 200 + { + 2, 15, 3, 10, + 15, 3, 10, 5, + 5, 10, 15, 18, + 5, 15, 3, 7, + 5, 18, 15, 7, + 18, 15, 7, 19, + }, + // 0b11001001 case 201 + { + 12, 0, 2, 8, + 15, 12, 2, 8, + 2, 15, 8, 7, + 2, 15, 7, 19, + 2, 7, 8, 5, + 2, 19, 7, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001010 case 202 + { + 0, 13, 1, 9, + 2, 15, 3, 5, + 15, 3, 5, 7, + 2, 15, 7, 19, + 2, 7, 5, 19, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001011 case 203 + { + 2, 13, 1, 9, + 2, 12, 13, 9, + 2, 12, 9, 8, + 2, 15, 12, 8, + 2, 15, 8, 7, + 2, 15, 7, 19, + 2, 19, 7, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001100 case 204 + { + 1, 14, 3, 5, + 14, 15, 3, 5, + 15, 3, 5, 7, + 14, 15, 5, 18, + 15, 7, 5, 18, + 15, 7, 18, 19, + }, + // 0b11001101 case 205 + { + 1, 12, 0, 8, + 1, 15, 12, 8, + 1, 15, 8, 7, + 1, 14, 15, 7, + 14, 15, 7, 19, + 14, 7, 1, 5, + 14, 7, 5, 19, + 14, 19, 5, 18, + }, + // 0b11001110 case 206 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 5, + 14, 15, 3, 5, + 14, 15, 5, 18, + 15, 3, 5, 7, + 15, 7, 5, 18, + 15, 7, 18, 19, + }, + // 0b11001111 case 207 + { + 15, 12, 13, 8, + 13, 15, 8, 9, + 14, 15, 13, 9, + 15, 8, 9, 7, + 14, 15, 9, 7, + 14, 7, 9, 5, + 15, 7, 14, 19, + 14, 19, 7, 5, + 14, 19, 5, 18, + }, + // 0b11010000 case 208 + { + 10, 11, 8, 4, + 10, 11, 4, 5, + 11, 8, 4, 16, + 11, 5, 10, 18, + 11, 16, 4, 19, + 11, 4, 5, 19, + 11, 5, 18, 19, + }, + // 0b11010001 case 209 + { + 3, 12, 0, 5, + 12, 0, 5, 4, + 12, 4, 5, 16, + 3, 12, 5, 16, + 3, 16, 5, 11, + 11, 16, 5, 19, + 11, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11010010 case 210 + { + 0, 13, 1, 9, + 10, 11, 8, 4, + 10, 11, 4, 5, + 10, 11, 5, 18, + 11, 8, 4, 16, + 11, 5, 18, 19, + 11, 4, 5, 19, + 11, 16, 4, 19, + }, + // 0b11010011 case 211 + { + 3, 13, 1, 4, + 13, 1, 4, 9, + 3, 12, 13, 4, + 3, 12, 4, 16, + 3, 16, 4, 11, + 11, 16, 4, 19, + 10, 11, 4, 19, + 10, 19, 4, 5, + 10, 19, 5, 18, + }, + // 0b11010100 case 212 + { + 1, 14, 2, 5, + 14, 2, 5, 18, + 2, 5, 18, 4, + 2, 4, 18, 8, + 2, 8, 18, 11, + 18, 8, 4, 16, + 18, 8, 16, 11, + 18, 11, 16, 19, + }, + // 0b11010101 case 213 + { + 12, 0, 3, 11, + 12, 0, 11, 4, + 12, 4, 11, 16, + 4, 11, 16, 19, + 11, 19, 4, 5, + 11, 19, 5, 18, + 1, 14, 2, 11, + 1, 14, 11, 5, + 14, 11, 5, 18, + }, + // 0b11010110 case 214 + { + 13, 2, 0, 5, + 0, 13, 5, 9, + 13, 14, 2, 5, + 5, 14, 2, 18, + 5, 18, 2, 11, + 5, 18, 11, 19, + 5, 11, 8, 19, + 8, 5, 19, 4, + 8, 4, 19, 16, + }, + // 0b11010111 case 215 + { + 3, 2, 11, 19, + 3, 14, 2, 19, + 3, 12, 14, 19, + 12, 13, 14, 19, + 12, 13, 19, 16, + 13, 14, 16, 9, + 9, 14, 16, 4, + 14, 19, 16, 4, + 14, 4, 9, 5, + 14, 19, 4, 5, + 14, 19, 5, 18, + }, + // 0b11011000 case 216 + { + 2, 15, 3, 10, + 15, 3, 10, 8, + 10, 15, 8, 5, + 15, 8, 5, 4, + 15, 5, 10, 18, + 15, 8, 4, 16, + 15, 4, 5, 19, + 15, 16, 4, 19, + 15, 5, 18, 19, + }, + // 0b11011001 case 217 + { + 2, 12, 0, 4, + 2, 15, 12, 4, + 15, 12, 4, 16, + 2, 15, 16, 19, + 2, 19, 16, 4, + 2, 19, 4, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11011010 case 218 + { + 0, 13, 1, 9, + 2, 15, 3, 10, + 15, 3, 10, 8, + 10, 15, 8, 5, + 5, 15, 8, 4, + 15, 5, 10, 18, + 15, 4, 5, 19, + 15, 8, 4, 16, + 15, 5, 18, 19, + 15, 16, 4, 19, + }, + // 0b11011011 case 219 + { + 13, 1, 2, 9, + 12, 13, 2, 9, + 12, 2, 15, 9, + 15, 9, 2, 4, + 15, 12, 9, 4, + 15, 12, 4, 16, + 15, 16, 2, 19, + 2, 16, 4, 19, + 2, 19, 4, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11011100 case 220 + { + 1, 14, 3, 5, + 14, 15, 3, 5, + 14, 15, 5, 18, + 15, 3, 5, 8, + 15, 8, 5, 4, + 15, 8, 4, 16, + 15, 16, 4, 19, + 15, 4, 5, 19, + 15, 5, 18, 19, + }, + // 0b11011101 case 221 + { + 14, 0, 1, 5, + 14, 15, 0, 5, + 14, 15, 5, 18, + 15, 12, 0, 5, + 12, 0, 5, 4, + 15, 12, 18, 19, + 12, 4, 5, 16, + 12, 5, 18, 16, + 12, 18, 19, 16, + }, + // 0b11011110 case 222 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 5, + 14, 3, 5, 18, + 14, 15, 3, 18, + 15, 3, 18, 19, + 3, 18, 19, 5, + 3, 5, 19, 4, + 3, 4, 19, 8, + 8, 4, 19, 16, + }, + // 0b11011111 case 223 + { + 14, 12, 13, 9, + 14, 15, 12, 9, + 14, 15, 9, 5, + 14, 15, 5, 18, + 15, 9, 5, 4, + 15, 12, 9, 4, + 15, 12, 4, 16, + 15, 16, 4, 19, + 15, 4, 5, 19, + 15, 5, 18, 19, + }, + // 0b11100000 case 224 + { + 9, 10, 11, 7, + 9, 10, 7, 4, + 10, 11, 7, 19, + 10, 4, 9, 17, + 10, 19, 7, 18, + 10, 7, 4, 18, + 10, 4, 17, 18, + }, + // 0b11100001 case 225 + { + 3, 12, 0, 8, + 9, 10, 11, 7, + 9, 10, 7, 4, + 10, 11, 7, 19, + 10, 4, 9, 17, + 10, 19, 7, 18, + 10, 7, 4, 18, + 10, 4, 17, 18, + }, + // 0b11100010 case 226 + { + 0, 13, 1, 4, + 13, 1, 4, 17, + 1, 4, 17, 10, + 10, 4, 17, 18, + 1, 4, 10, 11, + 10, 11, 4, 18, + 18, 11, 4, 7, + 18, 11, 7, 19, + }, + // 0b11100011 case 227 + { + 12, 1, 3, 4, + 12, 4, 3, 8, + 12, 13, 1, 4, + 13, 1, 4, 17, + 1, 4, 17, 10, + 10, 4, 17, 18, + 10, 11, 4, 18, + 11, 4, 18, 7, + 11, 7, 18, 19, + }, + // 0b11100100 case 228 + { + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 4, + 14, 11, 4, 7, + 14, 11, 7, 19, + 14, 4, 9, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + }, + // 0b11100101 case 229 + { + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 4, + 14, 11, 4, 7, + 14, 11, 7, 19, + 14, 4, 9, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + 3, 12, 0, 8, + }, + // 0b11100110 case 230 + { + 0, 13, 2, 4, + 13, 14, 2, 4, + 13, 14, 4, 17, + 14, 2, 17, 18, + 2, 4, 17, 18, + 2, 4, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11100111 case 231 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 13, 2, 8, 4, + 13, 14, 2, 4, + 13, 14, 4, 17, + 14, 2, 17, 18, + 2, 4, 17, 18, + 2, 4, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11101000 case 232 + { + 2, 15, 3, 7, + 2, 15, 7, 19, + 2, 19, 7, 4, + 2, 19, 4, 9, + 9, 19, 4, 17, + 2, 19, 9, 10, + 9, 10, 19, 17, + 10, 19, 17, 18, + }, + // 0b11101001 case 233 + { + 2, 12, 0, 7, + 12, 0, 7, 8, + 2, 15, 12, 7, + 2, 15, 7, 19, + 2, 19, 7, 10, + 10, 19, 7, 18, + 9, 10, 7, 18, + 9, 18, 7, 4, + 9, 18, 4, 17, + }, + // 0b11101010 case 234 + { + 0, 13, 1, 10, + 0, 13, 10, 17, + 0, 17, 10, 4, + 10, 4, 17, 18, + 10, 7, 4, 18, + 2, 15, 3, 10, + 15, 3, 10, 7, + 10, 15, 7, 18, + 15, 7, 18, 19, + }, + // 0b11101011 case 235 + { + 13, 1, 2, 10, + 13, 2, 15, 10, + 13, 15, 12, 10, + 12, 13, 10, 18, + 10, 15, 12, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 8, + 12, 18, 19, 8, + 8, 17, 18, 4, + 8, 4, 18, 7, + 19, 8, 18, 7, + }, + // 0b11101100 case 236 + { + 1, 15, 3, 7, + 1, 14, 15, 7, + 14, 15, 7, 19, + 1, 14, 19, 18, + 1, 18, 19, 7, + 1, 18, 7, 4, + 1, 18, 4, 9, + 9, 18, 4, 17, + }, + // 0b11101101 case 237 + { + 1, 12, 0, 8, + 1, 15, 12, 8, + 1, 14, 15, 8, + 1, 14, 8, 7, + 14, 15, 8, 7, + 14, 15, 7, 19, + 1, 14, 19, 18, + 1, 18, 19, 7, + 1, 18, 7, 4, + 4, 1, 18, 9, + 9, 18, 4, 17, + }, + // 0b11101110 case 238 + { + 13, 3, 0, 4, + 13, 15, 3, 4, + 15, 3, 4, 7, + 13, 14, 15, 7, + 13, 14, 7, 4, + 14, 15, 7, 19, + 13, 14, 4, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + }, + // 0b11101111 case 239 + { + 14, 15, 12, 18, + 12, 13, 14, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 8, + 12, 18, 19, 8, + 8, 17, 18, 4, + 18, 8, 4, 7, + 19, 8, 18, 7, + }, + // 0b11110000 case 240 + { + 9, 10, 11, 18, + 8, 9, 11, 18, + 8, 9, 18, 17, + 18, 11, 8, 19, + 8, 17, 18, 16, + 8, 18, 19, 16, + }, + // 0b11110001 case 241 + { + 3, 12, 0, 11, + 12, 0, 11, 9, + 11, 12, 9, 16, + 9, 10, 11, 16, + 10, 11, 16, 19, + 9, 10, 16, 17, + 10, 19, 16, 18, + 10, 16, 17, 18, + }, + // 0b11110010 case 242 + { + 0, 13, 1, 10, + 0, 13, 10, 8, + 8, 13, 10, 17, + 8, 17, 10, 18, + 8, 17, 18, 16, + 11, 8, 10, 16, + 11, 16, 10, 18, + 11, 16, 18, 19, + }, + // 0b11110011 case 243 + { + 12, 1, 3, 11, + 12, 13, 1, 11, + 13, 1, 11, 10, + 11, 13, 10, 18, + 11, 13, 18, 19, + 12, 13, 11, 19, + 12, 13, 18, 17, + 12, 17, 18, 19, + 12, 17, 19, 16, + }, + // 0b11110100 case 244 + { + 1, 14, 2, 11, + 1, 14, 11, 9, + 14, 11, 9, 18, + 11, 9, 18, 19, + 9, 18, 19, 17, + 8, 9, 11, 19, + 8, 9, 19, 17, + 8, 17, 19, 16, + }, + // 0b11110101 case 245 + { + 3, 12, 0, 11, + 12, 0, 11, 9, + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 18, + 12, 9, 11, 19, + 9, 18, 11, 19, + 12, 9, 19, 16, + 9, 18, 19, 17, + 9, 19, 16, 17, + }, + // 0b11110110 case 246 + { + 0, 13, 2, 8, + 13, 2, 8, 11, + 13, 14, 2, 11, + 13, 14, 11, 19, + 13, 11, 8, 19, + 13, 19, 8, 16, + 13, 14, 19, 18, + 13, 19, 16, 17, + 13, 18, 19, 17, + }, + // 0b11110111 case 247 + { + 12, 2, 3, 11, + 12, 14, 2, 11, + 12, 13, 14, 11, + 13, 14, 11, 18, + 12, 13, 11, 18, + 12, 18, 11, 19, + 12, 13, 18, 17, + 12, 18, 19, 16, + 12, 17, 18, 16, + }, + // 0b11111000 case 248 + { + 2, 15, 3, 10, + 15, 3, 10, 8, + 15, 8, 10, 19, + 8, 10, 19, 16, + 16, 10, 19, 18, + 8, 9, 10, 16, + 16, 9, 10, 18, + 9, 18, 16, 17, + }, + // 0b11111001 case 249 + { + 2, 15, 0, 10, + 15, 12, 0, 10, + 12, 0, 10, 9, + 10, 15, 9, 18, + 15, 12, 9, 18, + 12, 9, 18, 17, + 18, 15, 12, 19, + 12, 17, 18, 19, + 12, 17, 19, 16, + }, + // 0b11111010 case 250 + { + 0, 13, 1, 8, + 13, 1, 8, 10, + 8, 13, 10, 16, + 13, 10, 16, 18, + 13, 18, 16, 17, + 2, 15, 3, 10, + 15, 3, 10, 8, + 15, 8, 10, 18, + 15, 8, 18, 16, + 15, 16, 18, 19, + }, + // 0b11111011 case 251 + { + 2, 1, 10, 18, + 2, 15, 1, 18, + 15, 13, 1, 18, + 15, 12, 13, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 16, + 12, 18, 19, 16, + }, + // 0b11111100 case 252 + { + 1, 14, 3, 9, + 14, 3, 9, 8, + 14, 15, 3, 8, + 9, 14, 8, 17, + 14, 15, 8, 17, + 17, 15, 8, 16, + 14, 15, 17, 18, + 15, 17, 18, 19, + 15, 16, 17, 19, + }, + // 0b11111101 case 253 + { + 1, 0, 9, 17, + 14, 0, 1, 17, + 14, 12, 0, 17, + 14, 15, 12, 17, + 14, 15, 17, 18, + 15, 12, 17, 16, + 15, 17, 18, 19, + 15, 16, 17, 19, + }, + // 0b11111110 case 254 + { + 0, 3, 8, 16, + 13, 3, 0, 16, + 13, 15, 3, 16, + 13, 14, 15, 16, + 13, 14, 16, 17, + 14, 15, 16, 19, + 14, 16, 17, 18, + 14, 19, 16, 18, + }, + // 0b11111111 case 255 + { + 12, 14, 15, 19, + 12, 13, 14, 19, + 12, 13, 19, 16, + 13, 14, 19, 18, + 13, 18, 19, 17, + 13, 19, 16, 17, + }, +} + +//----------------------------------------------------------------------------- diff --git a/render/marchhex20.go b/render/marchhex20.go index e9a33b666..3f88d58cd 100644 --- a/render/marchhex20.go +++ b/render/marchhex20.go @@ -8,9 +8,9 @@ import ( //----------------------------------------------------------------------------- -func marchingCubesHex20(s sdf.SDF3, box sdf.Box3, step float64) []*Hex20 { +func marchingCubesHex20(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { - var fes []*Hex20 + var fes []*Fe size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) @@ -57,7 +57,7 @@ func marchingCubesHex20(s sdf.SDF3, box sdf.Box3, step float64) []*Hex20 { l.Get(1, y, z+1), l.Get(1, y+1, z+1), l.Get(0, y+1, z+1)} - fes = append(fes, mcToHex20(corners, values, 0, z)...) + fes = append(fes, mcToHex20(corners, values, 0, x, y, z)...) p.Z += dz } p.Y += dy @@ -70,8 +70,8 @@ func marchingCubesHex20(s sdf.SDF3, box sdf.Box3, step float64) []*Hex20 { //----------------------------------------------------------------------------- -func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex20 { - result := make([]*Hex20, 0) +func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { + result := make([]*Fe, 0) anyPositive := false for i := 0; i < 8; i++ { @@ -88,9 +88,11 @@ func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex20 { // TODO: Come up with a more sophisticated approach? if !anyPositive { - fe := Hex20{ - V: [20]v3.Vec{}, - Layer: layerZ, + fe := Fe{ + V: make([]v3.Vec, 20), + X: layerX, + Y: layerY, + Z: layerZ, } // Refer to CalculiX solver documentation: diff --git a/render/marchhex20tet10.go b/render/marchhex20tet10.go new file mode 100644 index 000000000..f8a1224ed --- /dev/null +++ b/render/marchhex20tet10.go @@ -0,0 +1,83 @@ +package render + +import ( + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +//----------------------------------------------------------------------------- + +func marchingCubesHex20Tet10(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { + var fes []*Fe + size := box.Size() + base := box.Min + steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) + inc := size.Div(conv.V3iToV3(steps)) + + // start the evaluation routines + evalRoutines() + + // create the SDF layer cache + l := newLayerXY(base, inc, steps) + // evaluate the SDF for z = 0 + l.Evaluate(s, 0) + + nx, ny, nz := steps.X, steps.Y, steps.Z + dx, dy, dz := inc.X, inc.Y, inc.Z + + var p v3.Vec + p.Z = base.Z + for z := 0; z < nz; z++ { + // read the z + 1 layer + l.Evaluate(s, z+1) + // process all cubes in the z and z + 1 layers + p.X = base.X + for x := 0; x < nx; x++ { + p.Y = base.Y + for y := 0; y < ny; y++ { + x0, y0, z0 := p.X, p.Y, p.Z + x1, y1, z1 := x0+dx, y0+dy, z0+dz + corners := [8]v3.Vec{ + {x0, y0, z0}, + {x1, y0, z0}, + {x1, y1, z0}, + {x0, y1, z0}, + {x0, y0, z1}, + {x1, y0, z1}, + {x1, y1, z1}, + {x0, y1, z1}} + values := [8]float64{ + l.Get(x, y, 0), + l.Get(x+1, y, 0), + l.Get(x+1, y+1, 0), + l.Get(x, y+1, 0), + l.Get(x, y, 1), + l.Get(x+1, y, 1), + l.Get(x+1, y+1, 1), + l.Get(x, y+1, 1), + } + fes = append(fes, mcToHex20Tet10(corners, values, 0, x, y, z)...) + p.Y += dy + } + p.X += dx + } + p.Z += dz + } + + return fes +} + +//----------------------------------------------------------------------------- + +func mcToHex20Tet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { + result := mcToHex20(p, v, x, layerX, layerY, layerZ) + + if len(result) < 1 { + result = mcToTet10(p, v, x, layerX, layerY, layerZ) + } + + return result +} + +//----------------------------------------------------------------------------- diff --git a/render/marchhex8.go b/render/marchhex8.go index 4a3c92777..a13ac46ac 100644 --- a/render/marchhex8.go +++ b/render/marchhex8.go @@ -8,9 +8,9 @@ import ( //----------------------------------------------------------------------------- -func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { +func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { - var fes []*Hex8 + var fes []*Fe size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) @@ -57,7 +57,7 @@ func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { l.Get(1, y, z+1), l.Get(1, y+1, z+1), l.Get(0, y+1, z+1)} - fes = append(fes, mcToHex8(corners, values, 0, z)...) + fes = append(fes, mcToHex8(corners, values, 0, x, y, z)...) p.Z += dz } p.Y += dy @@ -70,8 +70,8 @@ func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Hex8 { //----------------------------------------------------------------------------- -func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { - result := make([]*Hex8, 0) +func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { + result := make([]*Fe, 0) anyPositive := false for i := 0; i < 8; i++ { @@ -88,9 +88,11 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Hex8 { // TODO: Come up with a more sophisticated approach? if !anyPositive { - fe := Hex8{ - V: [8]v3.Vec{}, - Layer: layerZ, + fe := Fe{ + V: make([]v3.Vec, 8), + X: layerX, + Y: layerY, + Z: layerZ, } // Refer to CalculiX solver documentation: diff --git a/render/marchhex8tet4.go b/render/marchhex8tet4.go new file mode 100644 index 000000000..c14f568f9 --- /dev/null +++ b/render/marchhex8tet4.go @@ -0,0 +1,82 @@ +package render + +import ( + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +//----------------------------------------------------------------------------- + +func marchingCubesHex8Tet4(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { + var fes []*Fe + size := box.Size() + base := box.Min + steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) + inc := size.Div(conv.V3iToV3(steps)) + + // start the evaluation routines + evalRoutines() + + // create the SDF layer cache + l := newLayerYZ(base, inc, steps) + // evaluate the SDF for x = 0 + l.Evaluate(s, 0) + + nx, ny, nz := steps.X, steps.Y, steps.Z + dx, dy, dz := inc.X, inc.Y, inc.Z + + var p v3.Vec + p.X = base.X + for x := 0; x < nx; x++ { + // read the x + 1 layer + l.Evaluate(s, x+1) + // process all cubes in the x and x + 1 layers + p.Y = base.Y + for y := 0; y < ny; y++ { + p.Z = base.Z + for z := 0; z < nz; z++ { + x0, y0, z0 := p.X, p.Y, p.Z + x1, y1, z1 := x0+dx, y0+dy, z0+dz + corners := [8]v3.Vec{ + {x0, y0, z0}, + {x1, y0, z0}, + {x1, y1, z0}, + {x0, y1, z0}, + {x0, y0, z1}, + {x1, y0, z1}, + {x1, y1, z1}, + {x0, y1, z1}} + values := [8]float64{ + l.Get(0, y, z), + l.Get(1, y, z), + l.Get(1, y+1, z), + l.Get(0, y+1, z), + l.Get(0, y, z+1), + l.Get(1, y, z+1), + l.Get(1, y+1, z+1), + l.Get(0, y+1, z+1)} + fes = append(fes, mcToHex8Tet4(corners, values, 0, x, y, z)...) + p.Z += dz + } + p.Y += dy + } + p.X += dx + } + + return fes +} + +//----------------------------------------------------------------------------- + +func mcToHex8Tet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { + result := mcToHex8(p, v, x, layerX, layerY, layerZ) + + if len(result) < 1 { + result = mcToTet4(p, v, x, layerX, layerY, layerZ) + } + + return result +} + +//----------------------------------------------------------------------------- diff --git a/render/marchtet10.go b/render/marchtet10.go index c6a3a84de..9d1f62f02 100644 --- a/render/marchtet10.go +++ b/render/marchtet10.go @@ -10,8 +10,8 @@ import ( //----------------------------------------------------------------------------- -func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { - var fes []*Tet10 +func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { + var fes []*Fe size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) @@ -59,7 +59,7 @@ func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { l.Get(x+1, y+1, 1), l.Get(x, y+1, 1), } - fes = append(fes, mcToTet10(corners, values, 0, z)...) + fes = append(fes, mcToTet10(corners, values, 0, x, y, z)...) p.Y += dy } p.X += dx @@ -72,7 +72,7 @@ func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Tet10 { //----------------------------------------------------------------------------- -func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { +func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { // which of the 0..255 patterns do we have? index := 0 for i := 0; i < 8; i++ { @@ -95,11 +95,13 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet10 { // Create the tetrahedra. table := mcTetrahedronTable[index] count := len(table) / 4 - result := make([]*Tet10, 0, count) + result := make([]*Fe, 0, count) for i := 0; i < count; i++ { - t := Tet10{ - V: [10]v3.Vec{}, - Layer: layerZ, + t := Fe{ + V: make([]v3.Vec, 10), + X: layerX, + Y: layerY, + Z: layerZ, } // Points on tetrahedron corners. diff --git a/render/marchtet4.go b/render/marchtet4.go index 5da52fbad..27efe7dbf 100644 --- a/render/marchtet4.go +++ b/render/marchtet4.go @@ -10,8 +10,8 @@ import ( //----------------------------------------------------------------------------- -func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { - var fes []*Tet4 +func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { + var fes []*Fe size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) @@ -58,7 +58,7 @@ func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { l.Get(1, y, z+1), l.Get(1, y+1, z+1), l.Get(0, y+1, z+1)} - fes = append(fes, mcToTet4(corners, values, 0, z)...) + fes = append(fes, mcToTet4(corners, values, 0, x, y, z)...) p.Z += dz } p.Y += dy @@ -71,7 +71,7 @@ func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Tet4 { //----------------------------------------------------------------------------- -func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { +func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { // which of the 0..255 patterns do we have? index := 0 for i := 0; i < 8; i++ { @@ -94,11 +94,13 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { // Create the tetrahedra. table := mcTetrahedronTable[index] count := len(table) / 4 - result := make([]*Tet4, 0, count) + result := make([]*Fe, 0, count) for i := 0; i < count; i++ { - t := Tet4{ - V: [4]v3.Vec{}, - Layer: layerZ, + t := Fe{ + V: make([]v3.Vec, 4), + X: layerX, + Y: layerY, + Z: layerZ, } t.V[0] = point(points, p, table[i*4+0]) @@ -127,2491 +129,3 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerZ int) []*Tet4 { } //----------------------------------------------------------------------------- - -// Specify the point to create the tetrahedra. -// Point can be on edges or corners. -// Index from 0 to 11 means an edge. -// Index from 12 to 19 means a corner. -// Corners were originally indexed from 0 to 7 but they are shifted by 12. -// So, corners are from 0+12 to 7+12 i.e. from 12 to 19. -func point(edges [12]v3.Vec, corners [8]v3.Vec, index int) v3.Vec { - if 0 <= index && index < 12 { - return edges[index] - } else if index < 20 { - return corners[index-12] - } else { - // Should never reach here. - return v3.Vec{} - } -} - -//----------------------------------------------------------------------------- - -// Specify the edges & corners used to create the tetrahedra. -// Keep the index from 0 to 11 for edges, -// but shift the index for corners. -// Corners were originally indexed from 0 to 7. -// So, corners would be indexed from 0+12 to 7+12 i.e. from 12 to 19. -// Manually created by: -// https://github.com/Megidd/tetrahedron-table -var mcTetrahedronTable = [256][]int{ - // 0b00000000 case 0: no cube corner has zero/negative value. - {}, - // 0b00000001 case 1: first cube corner has zero/negative value. - {12, 0, 3, 8}, - // 0b00000010 case 2 - {13, 1, 0, 9}, - // 0b00000011 case 3 - { - 12, 13, 3, 8, - 13, 1, 3, 8, - 13, 1, 8, 9, - }, - // 0b00000100 case 4 - {14, 2, 1, 10}, - // 0b00000101 case 5 - { - 12, 0, 3, 8, - 14, 2, 1, 10, - }, - // 0b00000110 case 6 - { - 13, 14, 0, 9, - 14, 2, 0, 9, - 14, 2, 9, 10, - }, - // 0b00000111 case 7 - { - 12, 13, 3, 8, - 13, 2, 3, 8, - 13, 14, 2, 8, - 14, 2, 8, 10, - 13, 14, 8, 10, - 13, 10, 8, 9, - }, - // 0b00001000 case 8 - { - 15, 3, 2, 11, - }, - // 0b00001001 case 9 - { - 12, 0, 2, 11, - 12, 2, 15, 11, - 12, 0, 11, 8, - }, - // 0b00001010 case 10 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - }, - // 0b00001011 case 11 - { - 15, 12, 2, 11, - 12, 1, 2, 11, - 12, 13, 1, 11, - 13, 1, 11, 9, - 12, 13, 11, 9, - 11, 12, 9, 8, - }, - // 0b00001100 case 12 - { - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00001101 case 13 - { - 12, 0, 1, 8, - 12, 1, 14, 8, - 1, 14, 8, 10, - 14, 15, 12, 8, - 14, 15, 8, 10, - 10, 15, 8, 11, - }, - // 0b00001110 case 14 - { - 0, 15, 3, 11, - 0, 14, 15, 11, - 0, 14, 11, 9, - 0, 13, 14, 9, - 14, 11, 9, 10, - }, - // 0b00001111 case 15 - { - 12, 13, 14, 10, - 12, 13, 10, 9, - 12, 9, 10, 8, - 12, 14, 15, 8, - 14, 15, 8, 10, - 15, 8, 10, 11, - }, - // 0b00010000 case 16 - {8, 4, 7, 16}, - // 0b00010001 case 17 - { - 12, 0, 3, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b00010010 case 18 - { - 8, 4, 7, 16, - 13, 1, 0, 9, - }, - // 0b00010011 case 19 - { - 3, 12, 1, 7, - 12, 13, 1, 7, - 12, 13, 7, 16, - 13, 1, 7, 9, - 13, 7, 16, 9, - 16, 9, 7, 4, - }, - // 0b00010100 case 20 - { - 8, 4, 7, 16, - 1, 14, 2, 10, - }, - // 0b00010101 case 21 - { - 1, 14, 2, 10, - 3, 12, 0, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b00010110 case 22 - { - 8, 4, 7, 16, - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 10, - }, - // 0b00010111 case 23 - { - 3, 12, 2, 7, - 12, 13, 2, 7, - 13, 2, 7, 4, - 13, 2, 4, 9, - 12, 13, 7, 16, - 16, 13, 7, 4, - 13, 14, 2, 9, - 14, 2, 9, 10, - }, - // 0b00011000 case 24 - { - 8, 4, 7, 16, - 2, 15, 3, 11, - }, - // 0b00011001 case 25 - { - 12, 0, 2, 4, - 12, 2, 15, 4, - 2, 15, 4, 11, - 12, 4, 15, 11, - 12, 4, 11, 7, - 12, 4, 7, 16, - }, - // 0b00011010 case 26 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - 8, 4, 7, 16, - }, - // 0b00011011 case 27 - { - 12, 2, 15, 11, - 12, 1, 2, 11, - 12, 13, 1, 11, - 13, 1, 11, 9, - 12, 13, 11, 9, - 12, 9, 11, 4, - 12, 4, 11, 16, - 11, 16, 4, 7, - }, - // 0b00011100 case 28 - { - 8, 4, 7, 16, - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00011101 case 29 - { - 1, 14, 15, 10, - 15, 1, 10, 11, - 12, 1, 15, 11, - 12, 0, 1, 4, - 12, 1, 11, 4, - 12, 4, 11, 7, - 12, 4, 7, 16, - }, - // 0b00011110 case 30 - { - 8, 4, 7, 16, - 13, 14, 0, 9, - 14, 3, 0, 9, - 14, 15, 3, 9, - 15, 3, 9, 11, - 14, 15, 9, 11, - 14, 11, 9, 10, - }, - // 0b00011111 case 31 - { - 13, 14, 15, 11, - 13, 14, 11, 9, - 14, 11, 9, 10, - 12, 13, 15, 9, - 12, 9, 15, 11, - 12, 9, 11, 7, - 12, 9, 7, 16, - 16, 9, 7, 4, - }, - // 0b00100000 case 32 - {9, 5, 4, 17}, - // 0b00100001 case 33 - { - 12, 0, 3, 8, - 9, 5, 4, 17, - }, - // 0b00100010 case 34 - { - 0, 13, 1, 5, - 0, 13, 5, 4, - 4, 13, 5, 17, - }, - // 0b00100011 case 35 - { - 13, 1, 3, 5, - 13, 3, 12, 5, - 12, 5, 3, 4, - 12, 4, 3, 8, - 12, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00100100 case 36 - { - 1, 14, 2, 10, - 9, 5, 4, 17, - }, - // 0b00100101 case 37 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 4, 9, 5, 17, - }, - // 0b00100110 case 38 - { - 0, 14, 2, 4, - 14, 2, 4, 5, - 14, 2, 5, 10, - 0, 13, 14, 4, - 13, 14, 4, 5, - 13, 5, 4, 17, - }, - // 0b00100111 case 39 - { - 13, 14, 2, 10, - 12, 13, 2, 10, - 12, 2, 3, 10, - 12, 10, 3, 8, - 12, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 4, - 13, 5, 4, 17, - }, - // 0b00101000 case 40 - { - 9, 5, 4, 17, - 2, 15, 3, 11, - }, - // 0b00101001 case 41 - { - 9, 5, 4, 17, - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - }, - // 0b00101010 case 42 - { - 2, 15, 3, 11, - 0, 13, 1, 4, - 4, 13, 1, 5, - 4, 13, 5, 17, - }, - // 0b00101011 case 43 - { - 2, 15, 12, 11, - 11, 12, 2, 8, - 12, 1, 2, 8, - 12, 13, 1, 8, - 8, 1, 2, 5, - 13, 1, 8, 5, - 8, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00101100 case 44 - { - 9, 5, 4, 17, - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00101101 case 45 - { - 9, 5, 4, 17, - 1, 14, 0, 10, - 14, 12, 0, 10, - 12, 0, 10, 8, - 14, 15, 12, 10, - 15, 12, 10, 8, - 15, 8, 10, 11, - }, - // 0b00101110 case 46 - { - 14, 15, 3, 11, - 14, 3, 0, 11, - 0, 14, 11, 5, - 14, 11, 5, 10, - 0, 13, 14, 5, - 0, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00101111 case 47 - { - 14, 15, 12, 8, - 14, 15, 8, 10, - 15, 8, 10, 11, - 12, 13, 14, 10, - 12, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 4, - 13, 5, 4, 17, - }, - // 0b00110000 case 48 - { - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - }, - // 0b00110001 case 49 - { - 3, 12, 0, 5, - 3, 12, 5, 7, - 12, 0, 7, 16, - 0, 5, 7, 16, - 0, 5, 16, 9, - 9, 5, 16, 17, - }, - // 0b00110010 case 50 - { - 0, 13, 1, 7, - 13, 1, 7, 5, - 0, 13, 5, 17, - 0, 5, 7, 17, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b00110011 case 51 - { - 12, 1, 3, 5, - 3, 12, 5, 7, - 12, 13, 1, 5, - 12, 13, 5, 17, - 12, 17, 5, 7, - 12, 17, 7, 16, - }, - // 0b00110100 case 52 - { - 1, 14, 2, 10, - 7, 8, 5, 16, - 8, 9, 5, 16, - 16, 9, 5, 17, - }, - // 0b00110101 case 53 - { - 1, 14, 2, 10, - 3, 12, 0, 5, - 3, 12, 5, 7, - 0, 9, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 12, - 12, 17, 7, 16, - }, - // 0b00110110 case 54 - { - 13, 14, 2, 10, - 0, 13, 2, 10, - 0, 10, 2, 8, - 0, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 17, - 8, 17, 5, 7, - 8, 17, 7, 16, - }, - // 0b00110111 case 55 - { - 13, 14, 2, 10, - 13, 2, 3, 10, - 13, 10, 3, 5, - 12, 13, 3, 5, - 12, 13, 5, 17, - 3, 12, 5, 7, - 12, 17, 5, 7, - 12, 17, 7, 16, - }, - // 0b00111000 case 56 - { - 15, 3, 2, 11, - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - }, - // 0b00111001 case 57 - { - 12, 0, 2, 9, - 15, 12, 2, 9, - 2, 15, 9, 11, - 15, 12, 9, 11, - 12, 9, 11, 7, - 12, 9, 7, 16, - 9, 7, 16, 5, - 9, 5, 16, 17, - }, - // 0b00111010 case 58 - { - 15, 3, 2, 11, - 0, 13, 1, 8, - 13, 1, 8, 7, - 13, 1, 7, 5, - 13, 7, 8, 16, - 13, 7, 16, 5, - 13, 5, 16, 17, - }, - // 0b00111011 case 59 - { - 12, 13, 1, 17, - 12, 17, 1, 5, - 12, 5, 1, 7, - 12, 17, 5, 7, - 12, 17, 7, 16, - 2, 12, 1, 7, - 15, 12, 2, 7, - 15, 7, 2, 11, - }, - // 0b00111100 case 60 - { - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - 14, 3, 1, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00111101 case 61 - { - 0, 9, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 16, - 0, 16, 7, 12, - 12, 0, 11, 7, - 14, 0, 1, 10, - 12, 0, 15, 11, - 14, 15, 0, 11, - 14, 11, 0, 10, - }, - // 0b00111110 case 62 - { - 15, 3, 0, 11, - 14, 15, 0, 11, - 14, 11, 0, 10, - 14, 0, 13, 10, - 0, 13, 10, 5, - 0, 13, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b00111111 case 63 - { - 12, 14, 15, 11, - 12, 14, 11, 10, - 12, 13, 14, 10, - 11, 12, 10, 7, - 12, 13, 10, 7, - 12, 13, 7, 16, - 13, 10, 7, 5, - 13, 5, 7, 17, - 13, 7, 16, 17, - }, - // 0b01000000 case 64 - {10, 6, 5, 18}, - // 0b01000001 case 65 - { - 12, 0, 3, 8, - 10, 6, 5, 18, - }, - // 0b01000010 case 66 - { - 0, 13, 1, 9, - 10, 6, 5, 18, - }, - // 0b01000011 case 67 - { - 10, 6, 5, 18, - 3, 12, 1, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - }, - // 0b01000100 case 68 - { - 1, 14, 2, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01000101 case 69 - { - 12, 0, 3, 8, - 14, 2, 1, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01000110 case 70 - { - 0, 13, 2, 6, - 0, 13, 6, 9, - 13, 14, 2, 6, - 13, 14, 6, 9, - 9, 14, 6, 5, - 14, 6, 5, 18, - }, - // 0b01000111 case 71 - { - 3, 12, 2, 8, - 12, 13, 2, 8, - 13, 2, 8, 9, - 13, 14, 2, 9, - 9, 2, 8, 5, - 9, 14, 2, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01001000 case 72 - { - 10, 6, 5, 18, - 15, 3, 2, 11, - }, - // 0b01001001 case 73 - { - 10, 6, 5, 18, - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - }, - // 0b01001010 case 74 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - 10, 6, 5, 18, - }, - // 0b01001011 case 75 - { - 10, 6, 5, 18, - 2, 15, 1, 11, - 15, 13, 1, 11, - 13, 1, 11, 9, - 15, 12, 13, 11, - 11, 12, 13, 9, - 11, 12, 9, 8, - }, - // 0b01001100 case 76 - { - 14, 15, 3, 11, - 1, 14, 3, 11, - 1, 11, 3, 5, - 1, 14, 11, 5, - 5, 14, 11, 6, - 5, 14, 6, 18, - }, - // 0b01001101 case 77 - { - 12, 0, 15, 8, - 15, 8, 0, 11, - 14, 0, 1, 5, - 14, 15, 0, 11, - 14, 0, 5, 6, - 14, 11, 0, 6, - 14, 6, 5, 18, - }, - // 0b01001110 case 78 - { - 0, 13, 14, 9, - 14, 15, 3, 11, - 14, 3, 0, 9, - 14, 11, 3, 6, - 14, 3, 9, 5, - 14, 6, 3, 5, - 14, 6, 5, 18, - }, - // 0b01001111 case 79 - { - 15, 12, 13, 8, - 13, 15, 8, 11, - 13, 11, 8, 9, - 13, 14, 15, 9, - 14, 15, 9, 11, - 9, 14, 11, 5, - 14, 11, 5, 6, - 14, 6, 5, 18, - }, - // 0b01010000 case 80 - { - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01010001 case 81 - { - 10, 6, 5, 18, - 12, 0, 3, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b01010010 case 82 - { - 13, 1, 0, 9, - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01010011 case 83 - { - 10, 6, 5, 18, - 12, 13, 1, 9, - 3, 12, 1, 9, - 3, 9, 1, 7, - 3, 12, 9, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - }, - // 0b01010100 case 84 - { - 8, 4, 7, 16, - 14, 2, 1, 6, - 1, 14, 6, 5, - 5, 14, 6, 18, - }, - // 0b01010101 case 85 - { - 3, 12, 0, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - 1, 14, 2, 5, - 14, 2, 5, 6, - 5, 14, 6, 18, - }, - // 0b01010110 case 86 - { - 8, 4, 7, 16, - 0, 13, 2, 6, - 0, 13, 6, 9, - 13, 14, 2, 6, - 13, 14, 6, 9, - 14, 6, 9, 5, - 14, 6, 5, 18, - }, - // 0b01010111 case 87 - { - 13, 2, 3, 9, - 13, 3, 12, 9, - 13, 14, 2, 9, - 14, 2, 9, 6, - 3, 12, 9, 7, - 12, 9, 7, 4, - 14, 6, 9, 5, - 12, 4, 7, 16, - 14, 6, 5, 18, - }, - // 0b01011000 case 88 - { - 8, 4, 7, 16, - 10, 6, 5, 18, - 15, 3, 2, 11, - }, - // 0b01011001 case 89 - { - 10, 6, 5, 18, - 2, 15, 0, 4, - 2, 15, 4, 11, - 15, 12, 0, 4, - 15, 12, 4, 11, - 11, 12, 4, 7, - 7, 12, 4, 16, - }, - // 0b01011010 case 90 - { - 13, 1, 0, 9, - 2, 15, 3, 11, - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01011011 case 91 - { - 10, 6, 5, 18, - 15, 1, 2, 11, - 15, 13, 1, 11, - 13, 1, 11, 9, - 15, 12, 13, 11, - 12, 13, 11, 9, - 12, 9, 11, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - }, - // 0b01011100 case 92 - { - 8, 4, 7, 16, - 1, 15, 3, 5, - 15, 3, 5, 6, - 15, 3, 6, 11, - 1, 14, 15, 6, - 1, 14, 6, 5, - 14, 6, 5, 18, - }, - // 0b01011101 case 93 - { - 15, 0, 1, 11, - 15, 12, 0, 11, - 1, 14, 15, 11, - 11, 12, 0, 4, - 11, 1, 14, 5, - 11, 12, 4, 7, - 11, 5, 14, 6, - 14, 6, 5, 18, - 12, 4, 7, 16, - }, - // 0b01011110 case 94 - { - 8, 4, 7, 16, - 13, 3, 0, 9, - 13, 15, 3, 9, - 15, 3, 9, 11, - 13, 14, 15, 9, - 14, 15, 9, 11, - 14, 11, 9, 5, - 14, 11, 5, 6, - 14, 6, 5, 18, - }, - // 0b01011111 case 95 - { - 15, 12, 13, 11, - 11, 12, 13, 9, - 11, 12, 9, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - 13, 14, 15, 9, - 14, 15, 9, 11, - 9, 14, 11, 5, - 5, 14, 11, 6, - 14, 6, 5, 18, - }, - // 0b01100000 case 96 - { - 9, 10, 4, 17, - 10, 6, 4, 17, - 10, 6, 17, 18, - }, - // 0b01100001 case 97 - { - 12, 0, 3, 8, - 4, 9, 6, 17, - 9, 10, 6, 17, - 17, 10, 6, 18, - }, - // 0b01100010 case 98 - { - 0, 13, 1, 6, - 1, 10, 6, 18, - 13, 1, 6, 18, - 0, 13, 6, 4, - 13, 18, 6, 4, - 13, 18, 4, 17, - }, - // 0b01100011 case 99 - { - 3, 12, 1, 8, - 12, 13, 1, 8, - 8, 13, 1, 17, - 1, 8, 17, 4, - 1, 6, 8, 4, - 1, 4, 17, 6, - 1, 6, 17, 10, - 17, 10, 6, 18, - }, - // 0b01100100 case 100 - { - 1, 14, 2, 6, - 1, 2, 4, 6, - 1, 14, 6, 18, - 1, 18, 6, 4, - 1, 18, 4, 9, - 9, 18, 4, 17, - }, - // 0b01100101 case 101 - { - 3, 12, 0, 8, - 1, 14, 2, 9, - 9, 14, 2, 4, - 14, 2, 4, 6, - 9, 14, 4, 17, - 14, 6, 4, 17, - 14, 6, 17, 18, - }, - // 0b01100110 case 102 - { - 0, 13, 2, 4, - 13, 14, 2, 4, - 14, 2, 4, 6, - 14, 18, 6, 4, - 14, 18, 4, 13, - 13, 18, 4, 17, - }, - // 0b01100111 case 103 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 13, 14, 2, 8, - 14, 2, 8, 4, - 13, 14, 8, 4, - 14, 2, 4, 6, - 13, 14, 4, 17, - 14, 4, 17, 6, - 14, 6, 17, 18, - }, - // 0b01101000 case 104 - { - 2, 15, 3, 11, - 4, 9, 6, 17, - 9, 10, 6, 17, - 10, 6, 17, 18, - }, - // 0b01101001 case 105 - { - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - 4, 9, 6, 17, - 9, 10, 6, 17, - 10, 6, 17, 18, - }, - // 0b01101010 case 106 - { - 2, 15, 3, 11, - 0, 13, 1, 6, - 0, 13, 6, 4, - 1, 10, 6, 4, - 13, 1, 4, 17, - 10, 6, 4, 18, - 17, 1, 4, 10, - 17, 10, 4, 18, - }, - // 0b01101011 case 107 - { - 15, 1, 2, 11, - 15, 12, 1, 11, - 12, 1, 11, 8, - 12, 13, 1, 8, - 8, 13, 1, 4, - 13, 1, 4, 17, - 1, 6, 4, 17, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01101100 case 108 - { - 1, 14, 3, 9, - 14, 15, 3, 9, - 15, 3, 9, 11, - 14, 15, 9, 11, - 14, 11, 9, 6, - 14, 6, 9, 18, - 9, 18, 6, 4, - 4, 9, 18, 17, - }, - // 0b01101101 case 109 - { - 12, 0, 1, 8, - 15, 12, 1, 8, - 15, 8, 1, 11, - 14, 15, 1, 11, - 1, 14, 11, 6, - 1, 14, 6, 18, - 1, 18, 6, 4, - 1, 18, 4, 17, - 1, 17, 4, 9, - }, - // 0b01101110 case 110 - { - 14, 15, 3, 11, - 0, 14, 3, 11, - 0, 13, 14, 11, - 0, 13, 11, 6, - 13, 14, 11, 6, - 13, 14, 6, 18, - 0, 13, 6, 4, - 13, 18, 6, 4, - 13, 18, 4, 17, - }, - // 0b01101111 case 111 - { - 15, 12, 13, 11, - 13, 14, 15, 11, - 12, 13, 11, 8, - 8, 13, 14, 4, - 14, 8, 4, 11, - 14, 11, 4, 6, - 13, 14, 4, 17, - 14, 4, 17, 6, - 14, 6, 17, 18, - }, - // 0b01110000 case 112 - { - 8, 9, 10, 7, - 9, 10, 7, 6, - 8, 9, 7, 16, - 9, 10, 6, 18, - 9, 7, 16, 17, - 9, 6, 7, 17, - 9, 18, 6, 17, - }, - // 0b01110001 case 113 - { - 12, 0, 3, 7, - 12, 0, 7, 16, - 0, 9, 10, 7, - 0, 9, 7, 16, - 9, 10, 16, 17, - 10, 7, 16, 17, - 10, 7, 17, 6, - 10, 6, 17, 18, - }, - // 0b01110010 case 114 - { - 0, 13, 1, 10, - 0, 13, 10, 8, - 13, 10, 8, 6, - 13, 6, 8, 7, - 13, 10, 6, 18, - 13, 7, 8, 16, - 13, 6, 7, 17, - 13, 18, 6, 17, - 13, 7, 16, 17, - }, - // 0b01110011 case 115 - { - 3, 12, 13, 7, - 12, 13, 7, 16, - 13, 1, 3, 7, - 13, 1, 16, 17, - 1, 7, 16, 6, - 1, 6, 16, 17, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01110100 case 116 - { - 1, 14, 2, 6, - 1, 14, 6, 18, - 1, 18, 6, 7, - 1, 8, 9, 16, - 1, 7, 8, 16, - 1, 18, 7, 16, - 1, 18, 16, 9, - 9, 18, 16, 17, - }, - // 0b01110101 case 117 - { - 3, 12, 0, 9, - 3, 12, 9, 7, - 12, 9, 7, 16, - 9, 7, 16, 17, - 9, 6, 7, 17, - 1, 14, 2, 9, - 14, 2, 9, 6, - 14, 6, 9, 17, - 14, 6, 17, 18, - }, - // 0b01110110 case 118 - { - 13, 14, 2, 6, - 0, 13, 2, 6, - 13, 14, 6, 18, - 0, 13, 18, 17, - 0, 17, 18, 6, - 0, 17, 6, 7, - 0, 17, 7, 16, - 0, 7, 8, 16, - }, - // 0b01110111 case 119 - { - 12, 2, 3, 7, - 12, 14, 2, 7, - 14, 2, 7, 6, - 12, 13, 14, 7, - 12, 13, 7, 16, - 14, 6, 7, 18, - 14, 18, 7, 16, - 13, 14, 16, 18, - 13, 18, 16, 17, - }, - // 0b01111000 case 120 - { - 2, 15, 3, 11, - 8, 9, 10, 7, - 9, 10, 7, 6, - 9, 10, 6, 18, - 8, 9, 7, 16, - 9, 18, 6, 17, - 9, 6, 7, 17, - 9, 7, 16, 17, - }, - // 0b01111001 case 121 - { - 15, 0, 2, 7, - 15, 7, 2, 11, - 15, 12, 0, 7, - 12, 0, 7, 16, - 16, 0, 7, 9, - 16, 9, 7, 17, - 9, 10, 7, 17, - 10, 7, 17, 18, - 10, 7, 18, 6, - }, - // 0b01111010 case 122 - { - 15, 3, 2, 11, - 0, 13, 1, 10, - 0, 13, 10, 8, - 13, 10, 8, 6, - 8, 13, 6, 7, - 13, 6, 7, 17, - 13, 10, 6, 17, - 13, 7, 8, 17, - 17, 10, 6, 18, - 17, 7, 8, 16, - }, - // 0b01111011 case 123 - { - 15, 1, 2, 11, - 15, 12, 1, 11, - 12, 13, 1, 11, - 13, 1, 11, 7, - 12, 13, 11, 7, - 12, 13, 7, 16, - 13, 7, 16, 17, - 13, 1, 7, 17, - 1, 7, 17, 6, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01111100 case 124 - { - 3, 11, 6, 15, - 1, 15, 3, 6, - 1, 14, 15, 6, - 1, 14, 6, 18, - 1, 18, 6, 9, - 9, 18, 6, 17, - 8, 9, 6, 17, - 8, 17, 6, 7, - 8, 17, 7, 16, - }, - // 0b01111101 case 125 - { - 12, 0, 1, 9, - 12, 1, 14, 9, - 12, 14, 15, 9, - 12, 9, 15, 17, - 14, 15, 9, 17, - 15, 12, 17, 16, - 15, 17, 14, 18, - 15, 16, 17, 7, - 15, 17, 18, 6, - 15, 7, 17, 11, - 15, 17, 6, 11, - 11, 6, 7, 17, - }, - // 0b01111110 case 126 - { - 15, 3, 0, 11, - 14, 15, 0, 11, - 0, 14, 11, 6, - 0, 13, 14, 6, - 13, 14, 6, 18, - 0, 13, 18, 17, - 0, 18, 6, 17, - 0, 17, 6, 7, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b01111111 case 127 - { - 6, 7, 11, 15, - 12, 13, 15, 7, - 13, 14, 15, 7, - 14, 15, 7, 6, - 13, 14, 7, 6, - 13, 14, 6, 18, - 12, 13, 7, 16, - 13, 18, 6, 17, - 13, 6, 7, 17, - 13, 7, 16, 17, - }, - // 0b10000000 case 128 - { - 11, 7, 6, 19, - }, - // 0b10000001 case 129 - { - 3, 12, 0, 8, - 11, 7, 6, 19, - }, - // 0b10000010 case 130 - { - 0, 13, 1, 9, - 11, 7, 6, 19, - }, - // 0b10000011 case 131 - { - 11, 7, 6, 19, - 3, 12, 1, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - }, - // 0b10000100 case 132 - { - 1, 14, 2, 10, - 11, 7, 6, 19, - }, - // 0b10000101 case 133 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 11, 7, 6, 19, - }, - // 0b10000110 case 134 - { - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 10, - 11, 7, 6, 19, - }, - // 0b10000111 case 135 - { - 12, 2, 3, 8, - 12, 14, 2, 8, - 14, 2, 8, 10, - 12, 13, 14, 8, - 13, 14, 8, 10, - 13, 10, 8, 9, - 11, 7, 6, 19, - }, - // 0b10001000 case 136 - { - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001001 case 137 - { - 2, 15, 0, 6, - 15, 12, 0, 6, - 12, 0, 6, 7, - 12, 0, 7, 8, - 15, 12, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001010 case 138 - { - 0, 13, 1, 9, - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001011 case 139 - { - 12, 13, 1, 9, - 12, 9, 1, 8, - 12, 1, 2, 8, - 2, 8, 1, 7, - 2, 7, 1, 6, - 2, 15, 12, 8, - 2, 15, 8, 7, - 2, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10001100 case 140 - { - 15, 3, 1, 7, - 14, 15, 1, 7, - 1, 14, 7, 6, - 1, 14, 6, 10, - 14, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10001101 case 141 - { - 14, 0, 1, 10, - 14, 12, 0, 10, - 12, 0, 10, 8, - 14, 15, 12, 10, - 15, 12, 10, 8, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - }, - // 0b10001110 case 142 - { - 0, 13, 14, 9, - 14, 0, 9, 10, - 14, 15, 0, 10, - 15, 3, 0, 10, - 10, 3, 0, 7, - 10, 15, 3, 7, - 10, 15, 7, 6, - 6, 15, 7, 19, - }, - // 0b10001111 case 143 - { - 14, 15, 12, 8, - 14, 15, 8, 10, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - 12, 13, 14, 10, - 12, 13, 10, 8, - 8, 13, 10, 9, - }, - // 0b10010000 case 144 - { - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010001 case 145 - { - 3, 12, 0, 4, - 3, 4, 0, 6, - 12, 4, 6, 16, - 3, 12, 6, 16, - 3, 16, 6, 19, - 3, 19, 6, 11, - }, - // 0b10010010 case 146 - { - 0, 13, 1, 9, - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010011 case 147 - { - 3, 13, 1, 9, - 3, 12, 13, 9, - 3, 12, 9, 6, - 12, 9, 6, 4, - 3, 12, 4, 16, - 3, 16, 4, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10010100 case 148 - { - 1, 14, 2, 10, - 11, 8, 6, 19, - 8, 4, 6, 19, - 8, 4, 19, 16, - }, - // 0b10010101 case 149 - { - 1, 14, 2, 10, - 3, 12, 0, 11, - 12, 0, 11, 6, - 12, 6, 11, 19, - 0, 6, 19, 4, - 12, 0, 19, 4, - 12, 4, 19, 16, - }, - // 0b10010110 case 150 - { - 13, 14, 0, 9, - 14, 2, 0, 9, - 14, 2, 9, 10, - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010111 case 151 - { - 3, 14, 2, 10, - 3, 13, 14, 10, - 3, 13, 10, 9, - 3, 12, 13, 9, - 3, 12, 9, 4, - 3, 12, 4, 16, - 3, 16, 4, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10011000 case 152 - { - 2, 15, 3, 8, - 2, 15, 8, 4, - 15, 8, 4, 16, - 2, 15, 4, 6, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011001 case 153 - { - 12, 0, 2, 4, - 15, 12, 2, 4, - 2, 15, 4, 6, - 12, 4, 15, 16, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011010 case 154 - { - 0, 13, 1, 9, - 2, 15, 3, 8, - 2, 15, 8, 4, - 15, 8, 4, 16, - 2, 15, 4, 6, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011011 case 155 - { - 2, 13, 1, 9, - 2, 13, 9, 4, - 12, 13, 2, 4, - 15, 12, 2, 4, - 2, 15, 4, 6, - 15, 12, 4, 16, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011100 case 156 - { - 14, 3, 1, 8, - 14, 8, 1, 10, - 14, 15, 3, 8, - 14, 15, 8, 10, - 10, 15, 8, 6, - 15, 8, 6, 19, - 6, 19, 8, 4, - 19, 8, 4, 16, - }, - // 0b10011101 case 157 - { - 14, 0, 1, 10, - 14, 15, 0, 10, - 15, 12, 0, 10, - 12, 0, 10, 6, - 15, 12, 10, 6, - 12, 0, 6, 4, - 15, 12, 6, 19, - 12, 4, 6, 19, - 12, 4, 19, 16, - }, - // 0b10011110 case 158 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 10, - 14, 15, 3, 10, - 15, 3, 10, 6, - 15, 3, 6, 19, - 3, 6, 19, 4, - 3, 4, 19, 8, - 8, 4, 19, 16, - }, - // 0b10011111 case 159 - { - 12, 13, 14, 10, - 12, 13, 10, 9, - 12, 14, 15, 10, - 15, 9, 10, 6, - 15, 12, 9, 6, - 12, 9, 6, 4, - 15, 12, 6, 19, - 12, 6, 19, 4, - 12, 4, 19, 16, - }, - // 0b10100000 case 160 - { - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100001 case 161 - { - 3, 12, 0, 8, - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100010 case 162 - { - 0, 13, 1, 4, - 13, 1, 4, 5, - 4, 13, 5, 17, - 11, 7, 6, 19, - }, - // 0b10100011 case 163 - { - 3, 13, 1, 5, - 3, 12, 13, 5, - 12, 13, 5, 17, - 3, 17, 5, 4, - 3, 12, 17, 4, - 3, 12, 4, 8, - 11, 7, 6, 19, - }, - // 0b10100100 case 164 - { - 1, 14, 2, 10, - 11, 7, 6, 19, - 9, 5, 4, 17, - }, - // 0b10100101 case 165 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100110 case 166 - { - 14, 2, 0, 10, - 13, 14, 0, 10, - 0, 13, 10, 5, - 0, 13, 5, 4, - 13, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100111 case 167 - { - 11, 7, 6, 19, - 3, 14, 2, 10, - 3, 12, 14, 10, - 3, 12, 10, 8, - 12, 13, 14, 10, - 12, 13, 10, 8, - 8, 13, 10, 5, - 8, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b10101000 case 168 - { - 9, 5, 4, 17, - 2, 15, 3, 6, - 15, 3, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101001 case 169 - { - 9, 5, 4, 17, - 2, 12, 0, 6, - 12, 0, 6, 7, - 12, 0, 7, 8, - 2, 15, 12, 6, - 15, 12, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101010 case 170 - { - 0, 13, 1, 4, - 13, 1, 4, 5, - 13, 5, 4, 17, - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10101011 case 171 - { - 2, 12, 1, 8, - 12, 13, 1, 8, - 2, 15, 12, 8, - 8, 13, 1, 5, - 8, 13, 5, 4, - 4, 13, 5, 17, - 2, 15, 8, 6, - 15, 8, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101100 case 172 - { - 9, 5, 4, 17, - 1, 15, 3, 7, - 1, 14, 15, 7, - 1, 14, 7, 6, - 1, 14, 6, 10, - 14, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10101101 case 173 - { - 9, 5, 4, 17, - 1, 12, 0, 8, - 14, 12, 1, 8, - 14, 15, 12, 8, - 14, 8, 1, 10, - 14, 15, 8, 10, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - }, - // 0b10101110 case 174 - { - 13, 14, 0, 10, - 14, 3, 0, 10, - 14, 15, 3, 10, - 0, 13, 10, 5, - 0, 5, 10, 4, - 0, 13, 5, 4, - 13, 5, 4, 17, - 15, 3, 10, 7, - 15, 7, 10, 6, - 15, 7, 6, 19, - }, - // 0b10101111 case 175 - { - 12, 13, 14, 10, - 12, 14, 15, 10, - 12, 13, 10, 8, - 10, 15, 12, 8, - 10, 15, 8, 6, - 15, 8, 6, 7, - 15, 7, 6, 19, - 13, 10, 8, 4, - 13, 10, 4, 5, - 13, 5, 4, 17, - }, - // 0b10110000 case 176 - { - 11, 8, 9, 5, - 11, 8, 5, 6, - 8, 9, 5, 17, - 8, 6, 11, 19, - 8, 17, 5, 16, - 8, 5, 6, 16, - 8, 6, 19, 16, - }, - // 0b10110001 case 177 - { - 12, 0, 3, 11, - 11, 12, 0, 9, - 11, 12, 9, 6, - 12, 9, 6, 5, - 12, 6, 11, 19, - 12, 9, 5, 17, - 12, 17, 5, 16, - 12, 5, 6, 16, - 12, 6, 19, 16, - }, - // 0b10110010 case 178 - { - 0, 13, 1, 5, - 0, 13, 5, 17, - 0, 17, 5, 6, - 0, 17, 6, 11, - 11, 17, 6, 19, - 0, 17, 11, 19, - 0, 19, 11, 8, - 0, 17, 19, 8, - 8, 17, 19, 16, - }, - // 0b10110011 case 179 - { - 3, 13, 1, 5, - 3, 12, 13, 5, - 12, 13, 5, 17, - 3, 12, 17, 16, - 3, 17, 5, 16, - 3, 16, 5, 6, - 3, 16, 6, 11, - 16, 6, 11, 19, - }, - // 0b10110100 case 180 - { - 11, 8, 9, 5, - 11, 8, 5, 6, - 8, 9, 5, 17, - 8, 17, 5, 16, - 8, 5, 6, 16, - 8, 6, 11, 19, - 8, 6, 19, 16, - 1, 14, 2, 10, - }, - // 0b10110101 case 181 - { - 1, 14, 2, 10, - 3, 12, 0, 9, - 3, 12, 9, 11, - 11, 12, 9, 5, - 11, 12, 5, 6, - 12, 9, 5, 17, - 11, 12, 6, 19, - 12, 17, 5, 16, - 12, 5, 6, 16, - 12, 6, 19, 16, - }, - // 0b10110110 case 182 - { - 13, 14, 2, 10, - 0, 13, 2, 10, - 0, 10, 2, 5, - 0, 13, 10, 5, - 0, 13, 5, 17, - 0, 17, 5, 8, - 8, 17, 5, 16, - 11, 8, 5, 16, - 11, 16, 5, 6, - 11, 16, 6, 19, - }, - // 0b10110111 case 183 - { - 3, 14, 2, 10, - 3, 13, 14, 10, - 3, 12, 13, 10, - 3, 12, 10, 5, - 12, 13, 10, 5, - 12, 13, 5, 17, - 3, 12, 17, 16, - 3, 17, 5, 16, - 3, 16, 5, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10111000 case 184 - { - 8, 9, 5, 17, - 8, 17, 5, 16, - 2, 15, 3, 8, - 2, 15, 8, 5, - 2, 15, 5, 6, - 15, 8, 5, 6, - 6, 8, 5, 16, - 6, 15, 8, 19, - 6, 19, 8, 16, - }, - // 0b10111001 case 185 - { - 2, 15, 0, 6, - 15, 12, 0, 6, - 15, 12, 6, 19, - 12, 0, 19, 16, - 0, 6, 19, 16, - 0, 6, 16, 5, - 0, 5, 16, 9, - 16, 9, 5, 17, - }, - // 0b10111010 case 186 - { - 0, 13, 1, 8, - 13, 1, 8, 5, - 8, 13, 5, 17, - 8, 17, 5, 16, - 8, 16, 5, 6, - 2, 15, 3, 8, - 2, 15, 8, 6, - 15, 8, 6, 16, - 15, 16, 6, 19, - }, - // 0b10111011 case 187 - { - 2, 13, 1, 5, - 2, 12, 13, 5, - 12, 13, 5, 17, - 12, 17, 5, 16, - 12, 2, 15, 5, - 2, 15, 5, 6, - 15, 12, 5, 16, - 15, 16, 5, 6, - 15, 16, 6, 19, - }, - // 0b10111100 case 188 - { - 14, 3, 1, 6, - 1, 14, 6, 10, - 14, 15, 3, 6, - 15, 3, 6, 19, - 3, 6, 19, 8, - 8, 6, 19, 16, - 8, 6, 16, 9, - 9, 6, 16, 5, - 9, 5, 16, 17, - }, - // 0b10111101 case 189 - { - 14, 0, 1, 10, - 14, 12, 0, 10, - 14, 15, 12, 10, - 12, 0, 10, 6, - 10, 15, 12, 6, - 6, 15, 12, 19, - 12, 0, 19, 16, - 0, 6, 19, 16, - 0, 6, 16, 5, - 0, 5, 16, 9, - 16, 9, 5, 17, - }, - // 0b10111110 case 190 - { - 0, 15, 3, 8, - 0, 14, 15, 8, - 0, 13, 14, 8, - 8, 14, 15, 16, - 14, 15, 16, 19, - 13, 14, 8, 16, - 13, 14, 16, 17, - 14, 16, 17, 5, - 14, 16, 5, 10, - 10, 16, 5, 6, - 14, 19, 16, 10, - 10, 19, 16, 6, - }, - // 0b10111111 case 191 - { - 13, 15, 12, 16, - 13, 14, 15, 16, - 13, 14, 16, 17, - 14, 15, 16, 19, - 14, 16, 17, 5, - 14, 19, 16, 6, - 14, 6, 16, 10, - 14, 16, 5, 10, - 10, 6, 16, 5, - }, - // 0b11000000 case 192 - { - 10, 11, 5, 18, - 18, 11, 5, 7, - 11, 7, 18, 19, - }, - // 0b11000001 case 193 - { - 3, 12, 0, 8, - 5, 10, 11, 18, - 5, 18, 11, 7, - 11, 7, 18, 19, - }, - // 0b11000010 case 194 - { - 0, 13, 1, 9, - 10, 11, 5, 18, - 11, 7, 5, 18, - 11, 7, 18, 19, - }, - // 0b11000011 case 195 - { - 12, 1, 3, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - 10, 11, 5, 18, - 11, 7, 5, 18, - 11, 7, 18, 19, - }, - // 0b11000100 case 196 - { - 1, 14, 2, 7, - 1, 14, 7, 5, - 14, 2, 5, 18, - 2, 7, 5, 18, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11000101 case 197 - { - 1, 14, 2, 7, - 1, 14, 7, 5, - 14, 2, 5, 18, - 2, 7, 5, 18, - 2, 7, 18, 11, - 11, 7, 18, 19, - 3, 12, 0, 8, - }, - // 0b11000110 case 198 - { - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 5, - 14, 2, 5, 18, - 2, 9, 5, 7, - 2, 5, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11000111 case 199 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 8, 13, 2, 9, - 13, 14, 2, 9, - 9, 14, 2, 5, - 14, 2, 5, 18, - 2, 5, 18, 7, - 7, 18, 2, 11, - 18, 11, 7, 19, - }, - // 0b11001000 case 200 - { - 2, 15, 3, 10, - 15, 3, 10, 5, - 5, 10, 15, 18, - 5, 15, 3, 7, - 5, 18, 15, 7, - 18, 15, 7, 19, - }, - // 0b11001001 case 201 - { - 12, 0, 2, 8, - 15, 12, 2, 8, - 2, 15, 8, 7, - 2, 15, 7, 19, - 2, 7, 8, 5, - 2, 19, 7, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001010 case 202 - { - 0, 13, 1, 9, - 2, 15, 3, 5, - 15, 3, 5, 7, - 2, 15, 7, 19, - 2, 7, 5, 19, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001011 case 203 - { - 2, 13, 1, 9, - 2, 12, 13, 9, - 2, 12, 9, 8, - 2, 15, 12, 8, - 2, 15, 8, 7, - 2, 15, 7, 19, - 2, 19, 7, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001100 case 204 - { - 1, 14, 3, 5, - 14, 15, 3, 5, - 15, 3, 5, 7, - 14, 15, 5, 18, - 15, 7, 5, 18, - 15, 7, 18, 19, - }, - // 0b11001101 case 205 - { - 1, 12, 0, 8, - 1, 15, 12, 8, - 1, 15, 8, 7, - 1, 14, 15, 7, - 14, 15, 7, 19, - 14, 7, 1, 5, - 14, 7, 5, 19, - 14, 19, 5, 18, - }, - // 0b11001110 case 206 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 5, - 14, 15, 3, 5, - 14, 15, 5, 18, - 15, 3, 5, 7, - 15, 7, 5, 18, - 15, 7, 18, 19, - }, - // 0b11001111 case 207 - { - 15, 12, 13, 8, - 13, 15, 8, 9, - 14, 15, 13, 9, - 15, 8, 9, 7, - 14, 15, 9, 7, - 14, 7, 9, 5, - 15, 7, 14, 19, - 14, 19, 7, 5, - 14, 19, 5, 18, - }, - // 0b11010000 case 208 - { - 10, 11, 8, 4, - 10, 11, 4, 5, - 11, 8, 4, 16, - 11, 5, 10, 18, - 11, 16, 4, 19, - 11, 4, 5, 19, - 11, 5, 18, 19, - }, - // 0b11010001 case 209 - { - 3, 12, 0, 5, - 12, 0, 5, 4, - 12, 4, 5, 16, - 3, 12, 5, 16, - 3, 16, 5, 11, - 11, 16, 5, 19, - 11, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11010010 case 210 - { - 0, 13, 1, 9, - 10, 11, 8, 4, - 10, 11, 4, 5, - 10, 11, 5, 18, - 11, 8, 4, 16, - 11, 5, 18, 19, - 11, 4, 5, 19, - 11, 16, 4, 19, - }, - // 0b11010011 case 211 - { - 3, 13, 1, 4, - 13, 1, 4, 9, - 3, 12, 13, 4, - 3, 12, 4, 16, - 3, 16, 4, 11, - 11, 16, 4, 19, - 10, 11, 4, 19, - 10, 19, 4, 5, - 10, 19, 5, 18, - }, - // 0b11010100 case 212 - { - 1, 14, 2, 5, - 14, 2, 5, 18, - 2, 5, 18, 4, - 2, 4, 18, 8, - 2, 8, 18, 11, - 18, 8, 4, 16, - 18, 8, 16, 11, - 18, 11, 16, 19, - }, - // 0b11010101 case 213 - { - 12, 0, 3, 11, - 12, 0, 11, 4, - 12, 4, 11, 16, - 4, 11, 16, 19, - 11, 19, 4, 5, - 11, 19, 5, 18, - 1, 14, 2, 11, - 1, 14, 11, 5, - 14, 11, 5, 18, - }, - // 0b11010110 case 214 - { - 13, 2, 0, 5, - 0, 13, 5, 9, - 13, 14, 2, 5, - 5, 14, 2, 18, - 5, 18, 2, 11, - 5, 18, 11, 19, - 5, 11, 8, 19, - 8, 5, 19, 4, - 8, 4, 19, 16, - }, - // 0b11010111 case 215 - { - 3, 2, 11, 19, - 3, 14, 2, 19, - 3, 12, 14, 19, - 12, 13, 14, 19, - 12, 13, 19, 16, - 13, 14, 16, 9, - 9, 14, 16, 4, - 14, 19, 16, 4, - 14, 4, 9, 5, - 14, 19, 4, 5, - 14, 19, 5, 18, - }, - // 0b11011000 case 216 - { - 2, 15, 3, 10, - 15, 3, 10, 8, - 10, 15, 8, 5, - 15, 8, 5, 4, - 15, 5, 10, 18, - 15, 8, 4, 16, - 15, 4, 5, 19, - 15, 16, 4, 19, - 15, 5, 18, 19, - }, - // 0b11011001 case 217 - { - 2, 12, 0, 4, - 2, 15, 12, 4, - 15, 12, 4, 16, - 2, 15, 16, 19, - 2, 19, 16, 4, - 2, 19, 4, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11011010 case 218 - { - 0, 13, 1, 9, - 2, 15, 3, 10, - 15, 3, 10, 8, - 10, 15, 8, 5, - 5, 15, 8, 4, - 15, 5, 10, 18, - 15, 4, 5, 19, - 15, 8, 4, 16, - 15, 5, 18, 19, - 15, 16, 4, 19, - }, - // 0b11011011 case 219 - { - 13, 1, 2, 9, - 12, 13, 2, 9, - 12, 2, 15, 9, - 15, 9, 2, 4, - 15, 12, 9, 4, - 15, 12, 4, 16, - 15, 16, 2, 19, - 2, 16, 4, 19, - 2, 19, 4, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11011100 case 220 - { - 1, 14, 3, 5, - 14, 15, 3, 5, - 14, 15, 5, 18, - 15, 3, 5, 8, - 15, 8, 5, 4, - 15, 8, 4, 16, - 15, 16, 4, 19, - 15, 4, 5, 19, - 15, 5, 18, 19, - }, - // 0b11011101 case 221 - { - 14, 0, 1, 5, - 14, 15, 0, 5, - 14, 15, 5, 18, - 15, 12, 0, 5, - 12, 0, 5, 4, - 15, 12, 18, 19, - 12, 4, 5, 16, - 12, 5, 18, 16, - 12, 18, 19, 16, - }, - // 0b11011110 case 222 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 5, - 14, 3, 5, 18, - 14, 15, 3, 18, - 15, 3, 18, 19, - 3, 18, 19, 5, - 3, 5, 19, 4, - 3, 4, 19, 8, - 8, 4, 19, 16, - }, - // 0b11011111 case 223 - { - 14, 12, 13, 9, - 14, 15, 12, 9, - 14, 15, 9, 5, - 14, 15, 5, 18, - 15, 9, 5, 4, - 15, 12, 9, 4, - 15, 12, 4, 16, - 15, 16, 4, 19, - 15, 4, 5, 19, - 15, 5, 18, 19, - }, - // 0b11100000 case 224 - { - 9, 10, 11, 7, - 9, 10, 7, 4, - 10, 11, 7, 19, - 10, 4, 9, 17, - 10, 19, 7, 18, - 10, 7, 4, 18, - 10, 4, 17, 18, - }, - // 0b11100001 case 225 - { - 3, 12, 0, 8, - 9, 10, 11, 7, - 9, 10, 7, 4, - 10, 11, 7, 19, - 10, 4, 9, 17, - 10, 19, 7, 18, - 10, 7, 4, 18, - 10, 4, 17, 18, - }, - // 0b11100010 case 226 - { - 0, 13, 1, 4, - 13, 1, 4, 17, - 1, 4, 17, 10, - 10, 4, 17, 18, - 1, 4, 10, 11, - 10, 11, 4, 18, - 18, 11, 4, 7, - 18, 11, 7, 19, - }, - // 0b11100011 case 227 - { - 12, 1, 3, 4, - 12, 4, 3, 8, - 12, 13, 1, 4, - 13, 1, 4, 17, - 1, 4, 17, 10, - 10, 4, 17, 18, - 10, 11, 4, 18, - 11, 4, 18, 7, - 11, 7, 18, 19, - }, - // 0b11100100 case 228 - { - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 4, - 14, 11, 4, 7, - 14, 11, 7, 19, - 14, 4, 9, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - }, - // 0b11100101 case 229 - { - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 4, - 14, 11, 4, 7, - 14, 11, 7, 19, - 14, 4, 9, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - 3, 12, 0, 8, - }, - // 0b11100110 case 230 - { - 0, 13, 2, 4, - 13, 14, 2, 4, - 13, 14, 4, 17, - 14, 2, 17, 18, - 2, 4, 17, 18, - 2, 4, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11100111 case 231 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 13, 2, 8, 4, - 13, 14, 2, 4, - 13, 14, 4, 17, - 14, 2, 17, 18, - 2, 4, 17, 18, - 2, 4, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11101000 case 232 - { - 2, 15, 3, 7, - 2, 15, 7, 19, - 2, 19, 7, 4, - 2, 19, 4, 9, - 9, 19, 4, 17, - 2, 19, 9, 10, - 9, 10, 19, 17, - 10, 19, 17, 18, - }, - // 0b11101001 case 233 - { - 2, 12, 0, 7, - 12, 0, 7, 8, - 2, 15, 12, 7, - 2, 15, 7, 19, - 2, 19, 7, 10, - 10, 19, 7, 18, - 9, 10, 7, 18, - 9, 18, 7, 4, - 9, 18, 4, 17, - }, - // 0b11101010 case 234 - { - 0, 13, 1, 10, - 0, 13, 10, 17, - 0, 17, 10, 4, - 10, 4, 17, 18, - 10, 7, 4, 18, - 2, 15, 3, 10, - 15, 3, 10, 7, - 10, 15, 7, 18, - 15, 7, 18, 19, - }, - // 0b11101011 case 235 - { - 13, 1, 2, 10, - 13, 2, 15, 10, - 13, 15, 12, 10, - 12, 13, 10, 18, - 10, 15, 12, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 8, - 12, 18, 19, 8, - 8, 17, 18, 4, - 8, 4, 18, 7, - 19, 8, 18, 7, - }, - // 0b11101100 case 236 - { - 1, 15, 3, 7, - 1, 14, 15, 7, - 14, 15, 7, 19, - 1, 14, 19, 18, - 1, 18, 19, 7, - 1, 18, 7, 4, - 1, 18, 4, 9, - 9, 18, 4, 17, - }, - // 0b11101101 case 237 - { - 1, 12, 0, 8, - 1, 15, 12, 8, - 1, 14, 15, 8, - 1, 14, 8, 7, - 14, 15, 8, 7, - 14, 15, 7, 19, - 1, 14, 19, 18, - 1, 18, 19, 7, - 1, 18, 7, 4, - 4, 1, 18, 9, - 9, 18, 4, 17, - }, - // 0b11101110 case 238 - { - 13, 3, 0, 4, - 13, 15, 3, 4, - 15, 3, 4, 7, - 13, 14, 15, 7, - 13, 14, 7, 4, - 14, 15, 7, 19, - 13, 14, 4, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - }, - // 0b11101111 case 239 - { - 14, 15, 12, 18, - 12, 13, 14, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 8, - 12, 18, 19, 8, - 8, 17, 18, 4, - 18, 8, 4, 7, - 19, 8, 18, 7, - }, - // 0b11110000 case 240 - { - 9, 10, 11, 18, - 8, 9, 11, 18, - 8, 9, 18, 17, - 18, 11, 8, 19, - 8, 17, 18, 16, - 8, 18, 19, 16, - }, - // 0b11110001 case 241 - { - 3, 12, 0, 11, - 12, 0, 11, 9, - 11, 12, 9, 16, - 9, 10, 11, 16, - 10, 11, 16, 19, - 9, 10, 16, 17, - 10, 19, 16, 18, - 10, 16, 17, 18, - }, - // 0b11110010 case 242 - { - 0, 13, 1, 10, - 0, 13, 10, 8, - 8, 13, 10, 17, - 8, 17, 10, 18, - 8, 17, 18, 16, - 11, 8, 10, 16, - 11, 16, 10, 18, - 11, 16, 18, 19, - }, - // 0b11110011 case 243 - { - 12, 1, 3, 11, - 12, 13, 1, 11, - 13, 1, 11, 10, - 11, 13, 10, 18, - 11, 13, 18, 19, - 12, 13, 11, 19, - 12, 13, 18, 17, - 12, 17, 18, 19, - 12, 17, 19, 16, - }, - // 0b11110100 case 244 - { - 1, 14, 2, 11, - 1, 14, 11, 9, - 14, 11, 9, 18, - 11, 9, 18, 19, - 9, 18, 19, 17, - 8, 9, 11, 19, - 8, 9, 19, 17, - 8, 17, 19, 16, - }, - // 0b11110101 case 245 - { - 3, 12, 0, 11, - 12, 0, 11, 9, - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 18, - 12, 9, 11, 19, - 9, 18, 11, 19, - 12, 9, 19, 16, - 9, 18, 19, 17, - 9, 19, 16, 17, - }, - // 0b11110110 case 246 - { - 0, 13, 2, 8, - 13, 2, 8, 11, - 13, 14, 2, 11, - 13, 14, 11, 19, - 13, 11, 8, 19, - 13, 19, 8, 16, - 13, 14, 19, 18, - 13, 19, 16, 17, - 13, 18, 19, 17, - }, - // 0b11110111 case 247 - { - 12, 2, 3, 11, - 12, 14, 2, 11, - 12, 13, 14, 11, - 13, 14, 11, 18, - 12, 13, 11, 18, - 12, 18, 11, 19, - 12, 13, 18, 17, - 12, 18, 19, 16, - 12, 17, 18, 16, - }, - // 0b11111000 case 248 - { - 2, 15, 3, 10, - 15, 3, 10, 8, - 15, 8, 10, 19, - 8, 10, 19, 16, - 16, 10, 19, 18, - 8, 9, 10, 16, - 16, 9, 10, 18, - 9, 18, 16, 17, - }, - // 0b11111001 case 249 - { - 2, 15, 0, 10, - 15, 12, 0, 10, - 12, 0, 10, 9, - 10, 15, 9, 18, - 15, 12, 9, 18, - 12, 9, 18, 17, - 18, 15, 12, 19, - 12, 17, 18, 19, - 12, 17, 19, 16, - }, - // 0b11111010 case 250 - { - 0, 13, 1, 8, - 13, 1, 8, 10, - 8, 13, 10, 16, - 13, 10, 16, 18, - 13, 18, 16, 17, - 2, 15, 3, 10, - 15, 3, 10, 8, - 15, 8, 10, 18, - 15, 8, 18, 16, - 15, 16, 18, 19, - }, - // 0b11111011 case 251 - { - 2, 1, 10, 18, - 2, 15, 1, 18, - 15, 13, 1, 18, - 15, 12, 13, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 16, - 12, 18, 19, 16, - }, - // 0b11111100 case 252 - { - 1, 14, 3, 9, - 14, 3, 9, 8, - 14, 15, 3, 8, - 9, 14, 8, 17, - 14, 15, 8, 17, - 17, 15, 8, 16, - 14, 15, 17, 18, - 15, 17, 18, 19, - 15, 16, 17, 19, - }, - // 0b11111101 case 253 - { - 1, 0, 9, 17, - 14, 0, 1, 17, - 14, 12, 0, 17, - 14, 15, 12, 17, - 14, 15, 17, 18, - 15, 12, 17, 16, - 15, 17, 18, 19, - 15, 16, 17, 19, - }, - // 0b11111110 case 254 - { - 0, 3, 8, 16, - 13, 3, 0, 16, - 13, 15, 3, 16, - 13, 14, 15, 16, - 13, 14, 16, 17, - 14, 15, 16, 19, - 14, 16, 17, 18, - 14, 19, 16, 18, - }, - // 0b11111111 case 255 - { - 12, 14, 15, 19, - 12, 13, 14, 19, - 12, 13, 19, 16, - 13, 14, 19, 18, - 13, 18, 19, 17, - 13, 19, 16, 17, - }, -} - -//----------------------------------------------------------------------------- diff --git a/render/render.go b/render/render.go index a7bd7de69..e187d1063 100644 --- a/render/render.go +++ b/render/render.go @@ -31,10 +31,7 @@ type Render2 interface { // RenderFE renders a finite element mesh over the bounding volume of an sdf3. type RenderFE interface { - RenderTet4(sdf3 sdf.SDF3, output chan<- []*Tet4) - RenderTet10(sdf3 sdf.SDF3, output chan<- []*Tet10) - RenderHex8(sdf3 sdf.SDF3, output chan<- []*Hex8) - RenderHex20(sdf3 sdf.SDF3, output chan<- []*Hex20) + RenderFE(sdf3 sdf.SDF3, output chan<- []*Fe) Info(sdf3 sdf.SDF3) string LayerCounts(sdf3 sdf.SDF3) (int, int, int) } @@ -62,116 +59,26 @@ func ToTriangles( //----------------------------------------------------------------------------- -// ToTet4 renders an SDF3 to finite elements in the shape of 4-node tetrahedra. -func ToTet4( +// ToFem renders an SDF3 to finite elements in the shape of 4-node tetrahedra. +func ToFem( s sdf.SDF3, // sdf3 to render r RenderFE, // rendering method -) []Tet4 { +) []Fe { fmt.Printf("rendering %s\n", r.Info(s)) layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) // Will be filled by the rendering. - fes := make([]Tet4, 0) + fes := make([]Fe, 0) var wg sync.WaitGroup // Get the channel to be written to. - output := writeTet4(&wg, &fes) + output := writeFe(&wg, &fes) // run the renderer - r.RenderTet4(s, output) - // stop the writer reading on the channel - close(output) - // wait for the file write to complete - wg.Wait() - - return fes -} - -//----------------------------------------------------------------------------- - -// ToTet10 renders an SDF3 to finite elements in the shape of 10-node tetrahedra. -func ToTet10( - s sdf.SDF3, // sdf3 to render - r RenderFE, // rendering method -) []Tet10 { - fmt.Printf("rendering %s\n", r.Info(s)) - - layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) - fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) - - // Will be filled by the rendering. - fes := make([]Tet10, 0) - - var wg sync.WaitGroup - - // Get the channel to be written to. - output := writeTet10(&wg, &fes) - - // run the renderer - r.RenderTet10(s, output) - // stop the writer reading on the channel - close(output) - // wait for the file write to complete - wg.Wait() - - return fes -} - -//----------------------------------------------------------------------------- - -// ToHex8 renders an SDF3 to finite elements in the shape of 8-node hexahedra. -func ToHex8( - s sdf.SDF3, // sdf3 to render - r RenderFE, // rendering method -) []Hex8 { - fmt.Printf("rendering %s\n", r.Info(s)) - - layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) - fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) - - // Will be filled by the rendering. - fes := make([]Hex8, 0) - - var wg sync.WaitGroup - - // Get the channel to be written to. - output := writeHex8(&wg, &fes) - - // run the renderer - r.RenderHex8(s, output) - // stop the writer reading on the channel - close(output) - // wait for the file write to complete - wg.Wait() - - return fes -} - -//----------------------------------------------------------------------------- - -// ToHex20 renders an SDF3 to finite elements in the shape of 8-node hexahedra. -func ToHex20( - s sdf.SDF3, // sdf3 to render - r RenderFE, // rendering method -) []Hex20 { - fmt.Printf("rendering %s\n", r.Info(s)) - - layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) - fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) - - // Will be filled by the rendering. - fes := make([]Hex20, 0) - - var wg sync.WaitGroup - - // Get the channel to be written to. - output := writeHex20(&wg, &fes) - - // run the renderer - r.RenderHex20(s, output) + r.RenderFE(s, output) // stop the writer reading on the channel close(output) // wait for the file write to complete diff --git a/render/tet10.go b/render/tet10.go deleted file mode 100644 index e738b5315..000000000 --- a/render/tet10.go +++ /dev/null @@ -1,44 +0,0 @@ -package render - -import ( - "sync" - - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Tet10 is a 3D tetrahedron consisting of 10 nodes. -// It's a kind of finite element, FE. -// https://en.wikipedia.org/wiki/Tetrahedron -type Tet10 struct { - // Coordinates of corner nodes or vertices. - V [10]v3.Vec - // The Layer to which tetrahedron belongs. Layers are along Z axis. - // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store Layer along Z axis. - // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. - // Sampling/marching algorithm is expected to return the Layer to which a finite element belongs. - Layer int -} - -//----------------------------------------------------------------------------- - -// writeTet10 writes a stream of finite elements to an array. -func writeTet10(wg *sync.WaitGroup, tet10s *[]Tet10) chan<- []*Tet10 { - // External code writes to this channel. - // This goroutine reads the channel and stores finite elements. - c := make(chan []*Tet10) - - wg.Add(1) - go func() { - defer wg.Done() - // read finite elements from the channel and handle them - for fes := range c { - for _, fe := range fes { - *tet10s = append(*tet10s, *fe) - } - } - }() - - return c -} - -//----------------------------------------------------------------------------- diff --git a/render/tet4.go b/render/tet4.go deleted file mode 100644 index 3cd9dc4bc..000000000 --- a/render/tet4.go +++ /dev/null @@ -1,44 +0,0 @@ -package render - -import ( - "sync" - - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Tet4 is a 3D tetrahedron consisting of 4 nodes. -// It's a kind of finite element, FE. -// https://en.wikipedia.org/wiki/Tetrahedron -type Tet4 struct { - // Coordinates of 4 corner nodes or vertices. - V [4]v3.Vec - // The Layer to which tetrahedron belongs. Layers are along Z axis. - // For finite element analysis - FEA - of 3D printed objects, it's more efficient to store Layer along Z axis. - // The 3D print is done along the Z axis. Likewise, FEA is done along the Z axis. - // Sampling/marching algorithm is expected to return the Layer to which a finite element belongs. - Layer int -} - -//----------------------------------------------------------------------------- - -// writeTet4 writes a stream of finite elements to an array. -func writeTet4(wg *sync.WaitGroup, tet4s *[]Tet4) chan<- []*Tet4 { - // External code writes to this channel. - // This goroutine reads the channel and stores finite elements. - c := make(chan []*Tet4) - - wg.Add(1) - go func() { - defer wg.Done() - // read finite elements from the channel and handle them - for fes := range c { - for _, fe := range fes { - *tet4s = append(*tet4s, *fe) - } - } - }() - - return c -} - -//----------------------------------------------------------------------------- From 7efb6933b9e71590d4544f75789ac6442253d384 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 12:10:33 +0330 Subject: [PATCH 502/775] Refactor: simpler & cleaner? --- render/marchfe.go | 2880 +------------------------------------ render/marchfehelper.go | 2855 ++++++++++++++++++++++++++++++++++++ render/marchfelogic.go | 350 +++++ render/marchhex20.go | 133 -- render/marchhex20tet10.go | 83 -- render/marchhex8.go | 115 -- render/marchhex8tet4.go | 82 -- render/marchtet10.go | 140 -- render/marchtet4.go | 131 -- 9 files changed, 3206 insertions(+), 3563 deletions(-) create mode 100644 render/marchfehelper.go create mode 100644 render/marchfelogic.go delete mode 100644 render/marchhex20.go delete mode 100644 render/marchhex20tet10.go delete mode 100644 render/marchhex8.go delete mode 100644 render/marchhex8tet4.go delete mode 100644 render/marchtet10.go delete mode 100644 render/marchtet4.go diff --git a/render/marchfe.go b/render/marchfe.go index a16901739..5253902ba 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -2,13 +2,9 @@ package render import ( "fmt" - "math" - "sync" "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" - v3 "github.com/deadsy/sdfx/vec/v3" - "github.com/deadsy/sdfx/vec/v3i" ) //----------------------------------------------------------------------------- @@ -86,2881 +82,7 @@ func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output chan<- []*Fe) { bb1Size = bb1Size.Ceil().AddScalar(1) bb1Size = bb1Size.MulScalar(meshInc) bb := sdf.NewBox3(bb0.Center(), bb1Size) - switch r.order { - case Linear: - { - switch r.shape { - case Hexahedral: - { - output <- marchingCubesHex8(s, bb, meshInc) - } - case Tetrahedral: - { - output <- marchingCubesTet4(s, bb, meshInc) - } - case Both: - { - output <- marchingCubesHex8Tet4(s, bb, meshInc) - } - } - } - case Quadratic: - { - switch r.shape { - case Hexahedral: - { - output <- marchingCubesHex20(s, bb, meshInc) - } - case Tetrahedral: - { - output <- marchingCubesTet10(s, bb, meshInc) - } - case Both: - { - output <- marchingCubesHex20Tet10(s, bb, meshInc) - } - } - } - } -} - -//----------------------------------------------------------------------------- - -type layerXY struct { - base v3.Vec // base coordinate of layer - inc v3.Vec // dx, dy, dz for each step - steps v3i.Vec // number of x,y,z steps - val0 []float64 // SDF values for z layer - val1 []float64 // SDF values for z + dz layer -} - -func newLayerXY(base, inc v3.Vec, steps v3i.Vec) *layerXY { - return &layerXY{base, inc, steps, nil, nil} -} - -// Evaluate the SDF for a given XY layer -func (l *layerXY) Evaluate(s sdf.SDF3, z int) { - - // Swap the layers - l.val0, l.val1 = l.val1, l.val0 - - nx, ny := l.steps.X, l.steps.Y - dx, dy, dz := l.inc.X, l.inc.Y, l.inc.Z - - // allocate storage - if l.val1 == nil { - l.val1 = make([]float64, (nx+1)*(ny+1)) - } - - // setup the loop variables - var p v3.Vec - p.Z = l.base.Z + float64(z)*dz - - // define the base struct for requesting evaluation - eReq := evalReq{ - wg: new(sync.WaitGroup), - fn: s.Evaluate, - out: l.val1, - } - - // evaluate the layer - p.X = l.base.X - - // Performance doesn't seem to improve past 100. - const batchSize = 100 - - eReq.p = make([]v3.Vec, 0, batchSize) - for x := 0; x < nx+1; x++ { - p.Y = l.base.Y - for y := 0; y < ny+1; y++ { - eReq.p = append(eReq.p, p) - if len(eReq.p) == batchSize { - eReq.wg.Add(1) - evalProcessCh <- eReq - eReq.out = eReq.out[batchSize:] // shift the output slice for processing - eReq.p = make([]v3.Vec, 0, batchSize) // create a new slice for the next batch - } - p.Y += dy - } - p.X += dx - } - - // send any remaining points for processing - if len(eReq.p) > 0 { - eReq.wg.Add(1) - evalProcessCh <- eReq - } - - // Wait for all processing to complete before returning - eReq.wg.Wait() -} - -func (l *layerXY) Get(x, y, z int) float64 { - idz := x*(l.steps.Y+1) + y - if z == 0 { - return l.val0[idz] - } - return l.val1[idz] -} - -//----------------------------------------------------------------------------- - -// Specify the point to create the tetrahedra. -// Point can be on edges or corners. -// Index from 0 to 11 means an edge. -// Index from 12 to 19 means a corner. -// Corners were originally indexed from 0 to 7 but they are shifted by 12. -// So, corners are from 0+12 to 7+12 i.e. from 12 to 19. -func point(edges [12]v3.Vec, corners [8]v3.Vec, index int) v3.Vec { - if 0 <= index && index < 12 { - return edges[index] - } else if index < 20 { - return corners[index-12] - } else { - // Should never reach here. - return v3.Vec{} - } -} - -//----------------------------------------------------------------------------- - -// MATHEMATICA script is available here: -// https://math.stackexchange.com/a/4709610/197913 -func almostFlat(a, b, c, d v3.Vec) (bool, float64) { - ab := b.Sub(a) - ac := c.Sub(a) - ad := d.Sub(a) - - // Note that the `Norm` function of MATHEMATICA is equivalent to our `Length()` function. - nab := ab.Length() - ncd := d.Sub(c).Length() - nbd := d.Sub(b).Length() - nbc := c.Sub(b).Length() - nac := ac.Length() - nad := ad.Length() - - // Check for 0 edge lengths - if nab == 0 || ncd == 0 || - nbd == 0 || nbc == 0 || - nac == 0 || nad == 0 { - return true, 0 - } - - volume := 1.0 / 6.0 * math.Abs(ab.Cross(ac).Dot(ad)) - denom := (nab + ncd) * (nac + nbd) * (nad + nbc) - - // Tolerance derived from here: - // https://math.stackexchange.com/a/4709610/197913 - tolerance := 480.0 - - rho := tolerance * volume / denom - - return rho < 1, volume -} - -//----------------------------------------------------------------------------- - -// Reference: -// CCX source code: -// ccx_2.20/src/shape4tet.f -func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { - // Coordinates of the nodes. - var xl [3][4]float64 - - for i := 0; i < 4; i++ { - xl[0][i] = coords[i].X - xl[1][i] = coords[i].Y - xl[2][i] = coords[i].Z - } - - // Shape functions. - var shp [4][4]float64 - - shp[3][0] = 1.0 - xi - et - ze - shp[3][1] = xi - shp[3][2] = et - shp[3][3] = ze - - // local derivatives of the shape functions: xi-derivative - - shp[0][0] = -1.0 - shp[0][1] = 1.0 - shp[0][2] = 0.0 - shp[0][3] = 0.0 - - // local derivatives of the shape functions: eta-derivative - - shp[1][0] = -1.0 - shp[1][1] = 0.0 - shp[1][2] = 1.0 - shp[1][3] = 0.0 - - // local derivatives of the shape functions: zeta-derivative - - shp[2][0] = -1.0 - shp[2][1] = 0.0 - shp[2][2] = 0.0 - shp[2][3] = 1.0 - - // computation of the local derivative of the global coordinates (xs) - xs := [3][3]float64{} - for i := 0; i < 3; i++ { - for j := 0; j < 3; j++ { - xs[i][j] = 0.0 - for k := 0; k < 4; k++ { - xs[i][j] += xl[i][k] * shp[j][k] - } - } - } - - // computation of the jacobian determinant - xsj := xs[0][0]*(xs[1][1]*xs[2][2]-xs[1][2]*xs[2][1]) - - xs[0][1]*(xs[1][0]*xs[2][2]-xs[1][2]*xs[2][0]) + - xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) - - // According to CCX source code to detect nonpositive jacobian determinant in element - // - // Fortran threshold for non-positive Jacobian determinant is 1e-20. - // But, for example a bad element with non-positive Jacobian determinant - // of 0.0025717779019105687 is escaping the 1e-20 threshold. - // Seems like we need to make the threshold safer. - return xsj < 1e-20, xsj -} - -// Reference: -// CCX source code: -// ccx_2.20/src/shape10tet.f -func isBadGaussTet10(coords [10]v3.Vec, xi, et, ze float64) (bool, float64) { - // Coordinates of the nodes. - var xl [3][10]float64 - - for i := 0; i < 10; i++ { - xl[0][i] = coords[i].X - xl[1][i] = coords[i].Y - xl[2][i] = coords[i].Z - } - - // Shape functions. - var shp [4][10]float64 - - // Shape functions - a := 1.0 - xi - et - ze - shp[3][0] = (2.0*a - 1.0) * a - shp[3][1] = xi * (2.0*xi - 1.0) - shp[3][2] = et * (2.0*et - 1.0) - shp[3][3] = ze * (2.0*ze - 1.0) - shp[3][4] = 4.0 * xi * a - shp[3][5] = 4.0 * xi * et - shp[3][6] = 4.0 * et * a - shp[3][7] = 4.0 * ze * a - shp[3][8] = 4.0 * xi * ze - shp[3][9] = 4.0 * et * ze - - // Local derivatives of the shape functions: xi-derivative - shp[0][0] = 1.0 - 4.0*a - shp[0][1] = 4.0*xi - 1.0 - shp[0][2] = 0.0 - shp[0][3] = 0.0 - shp[0][4] = 4.0 * (a - xi) - shp[0][5] = 4.0 * et - shp[0][6] = -4.0 * et - shp[0][7] = -4.0 * ze - shp[0][8] = 4.0 * ze - shp[0][9] = 0.0 - - // Local derivatives of the shape functions: eta-derivative - shp[1][0] = 1.0 - 4.0*a - shp[1][1] = 0.0 - shp[1][2] = 4.0*et - 1.0 - shp[1][3] = 0.0 - shp[1][4] = -4.0 * xi - shp[1][5] = 4.0 * xi - shp[1][6] = 4.0 * (a - et) - shp[1][7] = -4.0 * ze - shp[1][8] = 0.0 - shp[1][9] = 4.0 * ze - - // Local derivatives of the shape functions: zeta-derivative - shp[2][0] = 1.0 - 4.0*a - shp[2][1] = 0.0 - shp[2][2] = 0.0 - shp[2][3] = 4.0*ze - 1.0 - shp[2][4] = -4.0 * xi - shp[2][5] = 0.0 - shp[2][6] = -4.0 * et - shp[2][7] = 4.0 * (a - ze) - shp[2][8] = 4.0 * xi - shp[2][9] = 4.0 * et - - // Computation of the local derivative of the global coordinates (xs) - var xs [3][3]float64 - for i := 0; i < 3; i++ { - for j := 0; j < 3; j++ { - xs[i][j] = 0.0 - for k := 0; k < 10; k++ { - xs[i][j] = xs[i][j] + xl[i][k]*shp[j][k] - } - } - } - - // computation of the jacobian determinant - xsj := xs[0][0]*(xs[1][1]*xs[2][2]-xs[1][2]*xs[2][1]) - - xs[0][1]*(xs[1][0]*xs[2][2]-xs[1][2]*xs[2][0]) + - xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) - - // According to CCX source code to detect nonpositive jacobian determinant in element - // - // Fortran threshold for non-positive Jacobian determinant is 1e-20. - // But, for example a bad element with non-positive Jacobian determinant - // of 0.0025717779019105687 is escaping the 1e-20 threshold. - // Seems like we need to make the threshold safer. - return xsj < 1e-20, xsj -} - -//----------------------------------------------------------------------------- - -func isBadTet4(coords [4]v3.Vec) (bool, float64) { - - // xi, et, and ze are the coordinates of the Gauss point - // in the integration scheme for the 4-node tetrahedral element. - // For this element type, there is typically only 1 Gauss point used, - // which is located at the centroid of the tetrahedron. - // The coordinates of this Gauss point are (xi, et, ze) = (1/4, 1/4, 1/4). - // Reference: - // ccx_2.20/src/gauss.f - var xi float64 = 0.25 - var et float64 = 0.25 - var ze float64 = 0.25 - - return isBadGaussTet4(coords, xi, et, ze) -} - -func isBadTet10(coords [10]v3.Vec) (bool, float64) { - // Gause points are according to CCX source code. - // Reference: - // ccx_2.20/src/gauss.f - var gaussPoints [4]v3.Vec - gaussPoints[0] = v3.Vec{0.138196601125011, 0.138196601125011, 0.138196601125011} - gaussPoints[1] = v3.Vec{0.585410196624968, 0.138196601125011, 0.138196601125011} - gaussPoints[2] = v3.Vec{0.138196601125011, 0.585410196624968, 0.138196601125011} - gaussPoints[3] = v3.Vec{0.138196601125011, 0.138196601125011, 0.585410196624968} - - var bad bool - var jacobianDeterminant float64 - - for i := 0; i < 4; i++ { - bad, jacobianDeterminant = isBadGaussTet10(coords, gaussPoints[i].X, gaussPoints[i].Y, gaussPoints[i].Z) - if bad { - return true, jacobianDeterminant - } - } - - return false, jacobianDeterminant -} - -//----------------------------------------------------------------------------- - -// If triangles are degenerate, then tetrahedra will be bad. -// To filter bad tetrahedra. -func degenerateTriangles(a, b, c, d v3.Vec) bool { - // 4 triangles are possible. - // Each triangle is a tetrahedron side. - t := Triangle3{} - t.V[0] = a - t.V[1] = b - t.V[2] = c - // Use the epsilon value of `vertexbuffer.go` - if t.Degenerate(0.0001) { - return true - } - t.V[0] = a - t.V[1] = b - t.V[2] = d - // Use the epsilon value of `vertexbuffer.go` - if t.Degenerate(0.0001) { - return true - } - t.V[0] = a - t.V[1] = c - t.V[2] = d - // Use the epsilon value of `vertexbuffer.go` - if t.Degenerate(0.0001) { - return true - } - t.V[0] = b - t.V[1] = c - t.V[2] = d - // Use the epsilon value of `vertexbuffer.go` - return t.Degenerate(0.0001) -} - -//----------------------------------------------------------------------------- - -// Specify the edges & corners used to create the tetrahedra. -// Keep the index from 0 to 11 for edges, -// but shift the index for corners. -// Corners were originally indexed from 0 to 7. -// So, corners would be indexed from 0+12 to 7+12 i.e. from 12 to 19. -// Manually created by: -// https://github.com/Megidd/tetrahedron-table -var mcTetrahedronTable = [256][]int{ - // 0b00000000 case 0: no cube corner has zero/negative value. - {}, - // 0b00000001 case 1: first cube corner has zero/negative value. - {12, 0, 3, 8}, - // 0b00000010 case 2 - {13, 1, 0, 9}, - // 0b00000011 case 3 - { - 12, 13, 3, 8, - 13, 1, 3, 8, - 13, 1, 8, 9, - }, - // 0b00000100 case 4 - {14, 2, 1, 10}, - // 0b00000101 case 5 - { - 12, 0, 3, 8, - 14, 2, 1, 10, - }, - // 0b00000110 case 6 - { - 13, 14, 0, 9, - 14, 2, 0, 9, - 14, 2, 9, 10, - }, - // 0b00000111 case 7 - { - 12, 13, 3, 8, - 13, 2, 3, 8, - 13, 14, 2, 8, - 14, 2, 8, 10, - 13, 14, 8, 10, - 13, 10, 8, 9, - }, - // 0b00001000 case 8 - { - 15, 3, 2, 11, - }, - // 0b00001001 case 9 - { - 12, 0, 2, 11, - 12, 2, 15, 11, - 12, 0, 11, 8, - }, - // 0b00001010 case 10 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - }, - // 0b00001011 case 11 - { - 15, 12, 2, 11, - 12, 1, 2, 11, - 12, 13, 1, 11, - 13, 1, 11, 9, - 12, 13, 11, 9, - 11, 12, 9, 8, - }, - // 0b00001100 case 12 - { - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00001101 case 13 - { - 12, 0, 1, 8, - 12, 1, 14, 8, - 1, 14, 8, 10, - 14, 15, 12, 8, - 14, 15, 8, 10, - 10, 15, 8, 11, - }, - // 0b00001110 case 14 - { - 0, 15, 3, 11, - 0, 14, 15, 11, - 0, 14, 11, 9, - 0, 13, 14, 9, - 14, 11, 9, 10, - }, - // 0b00001111 case 15 - { - 12, 13, 14, 10, - 12, 13, 10, 9, - 12, 9, 10, 8, - 12, 14, 15, 8, - 14, 15, 8, 10, - 15, 8, 10, 11, - }, - // 0b00010000 case 16 - {8, 4, 7, 16}, - // 0b00010001 case 17 - { - 12, 0, 3, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b00010010 case 18 - { - 8, 4, 7, 16, - 13, 1, 0, 9, - }, - // 0b00010011 case 19 - { - 3, 12, 1, 7, - 12, 13, 1, 7, - 12, 13, 7, 16, - 13, 1, 7, 9, - 13, 7, 16, 9, - 16, 9, 7, 4, - }, - // 0b00010100 case 20 - { - 8, 4, 7, 16, - 1, 14, 2, 10, - }, - // 0b00010101 case 21 - { - 1, 14, 2, 10, - 3, 12, 0, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b00010110 case 22 - { - 8, 4, 7, 16, - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 10, - }, - // 0b00010111 case 23 - { - 3, 12, 2, 7, - 12, 13, 2, 7, - 13, 2, 7, 4, - 13, 2, 4, 9, - 12, 13, 7, 16, - 16, 13, 7, 4, - 13, 14, 2, 9, - 14, 2, 9, 10, - }, - // 0b00011000 case 24 - { - 8, 4, 7, 16, - 2, 15, 3, 11, - }, - // 0b00011001 case 25 - { - 12, 0, 2, 4, - 12, 2, 15, 4, - 2, 15, 4, 11, - 12, 4, 15, 11, - 12, 4, 11, 7, - 12, 4, 7, 16, - }, - // 0b00011010 case 26 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - 8, 4, 7, 16, - }, - // 0b00011011 case 27 - { - 12, 2, 15, 11, - 12, 1, 2, 11, - 12, 13, 1, 11, - 13, 1, 11, 9, - 12, 13, 11, 9, - 12, 9, 11, 4, - 12, 4, 11, 16, - 11, 16, 4, 7, - }, - // 0b00011100 case 28 - { - 8, 4, 7, 16, - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00011101 case 29 - { - 1, 14, 15, 10, - 15, 1, 10, 11, - 12, 1, 15, 11, - 12, 0, 1, 4, - 12, 1, 11, 4, - 12, 4, 11, 7, - 12, 4, 7, 16, - }, - // 0b00011110 case 30 - { - 8, 4, 7, 16, - 13, 14, 0, 9, - 14, 3, 0, 9, - 14, 15, 3, 9, - 15, 3, 9, 11, - 14, 15, 9, 11, - 14, 11, 9, 10, - }, - // 0b00011111 case 31 - { - 13, 14, 15, 11, - 13, 14, 11, 9, - 14, 11, 9, 10, - 12, 13, 15, 9, - 12, 9, 15, 11, - 12, 9, 11, 7, - 12, 9, 7, 16, - 16, 9, 7, 4, - }, - // 0b00100000 case 32 - {9, 5, 4, 17}, - // 0b00100001 case 33 - { - 12, 0, 3, 8, - 9, 5, 4, 17, - }, - // 0b00100010 case 34 - { - 0, 13, 1, 5, - 0, 13, 5, 4, - 4, 13, 5, 17, - }, - // 0b00100011 case 35 - { - 13, 1, 3, 5, - 13, 3, 12, 5, - 12, 5, 3, 4, - 12, 4, 3, 8, - 12, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00100100 case 36 - { - 1, 14, 2, 10, - 9, 5, 4, 17, - }, - // 0b00100101 case 37 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 4, 9, 5, 17, - }, - // 0b00100110 case 38 - { - 0, 14, 2, 4, - 14, 2, 4, 5, - 14, 2, 5, 10, - 0, 13, 14, 4, - 13, 14, 4, 5, - 13, 5, 4, 17, - }, - // 0b00100111 case 39 - { - 13, 14, 2, 10, - 12, 13, 2, 10, - 12, 2, 3, 10, - 12, 10, 3, 8, - 12, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 4, - 13, 5, 4, 17, - }, - // 0b00101000 case 40 - { - 9, 5, 4, 17, - 2, 15, 3, 11, - }, - // 0b00101001 case 41 - { - 9, 5, 4, 17, - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - }, - // 0b00101010 case 42 - { - 2, 15, 3, 11, - 0, 13, 1, 4, - 4, 13, 1, 5, - 4, 13, 5, 17, - }, - // 0b00101011 case 43 - { - 2, 15, 12, 11, - 11, 12, 2, 8, - 12, 1, 2, 8, - 12, 13, 1, 8, - 8, 1, 2, 5, - 13, 1, 8, 5, - 8, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00101100 case 44 - { - 9, 5, 4, 17, - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00101101 case 45 - { - 9, 5, 4, 17, - 1, 14, 0, 10, - 14, 12, 0, 10, - 12, 0, 10, 8, - 14, 15, 12, 10, - 15, 12, 10, 8, - 15, 8, 10, 11, - }, - // 0b00101110 case 46 - { - 14, 15, 3, 11, - 14, 3, 0, 11, - 0, 14, 11, 5, - 14, 11, 5, 10, - 0, 13, 14, 5, - 0, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00101111 case 47 - { - 14, 15, 12, 8, - 14, 15, 8, 10, - 15, 8, 10, 11, - 12, 13, 14, 10, - 12, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 4, - 13, 5, 4, 17, - }, - // 0b00110000 case 48 - { - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - }, - // 0b00110001 case 49 - { - 3, 12, 0, 5, - 3, 12, 5, 7, - 12, 0, 7, 16, - 0, 5, 7, 16, - 0, 5, 16, 9, - 9, 5, 16, 17, - }, - // 0b00110010 case 50 - { - 0, 13, 1, 7, - 13, 1, 7, 5, - 0, 13, 5, 17, - 0, 5, 7, 17, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b00110011 case 51 - { - 12, 1, 3, 5, - 3, 12, 5, 7, - 12, 13, 1, 5, - 12, 13, 5, 17, - 12, 17, 5, 7, - 12, 17, 7, 16, - }, - // 0b00110100 case 52 - { - 1, 14, 2, 10, - 7, 8, 5, 16, - 8, 9, 5, 16, - 16, 9, 5, 17, - }, - // 0b00110101 case 53 - { - 1, 14, 2, 10, - 3, 12, 0, 5, - 3, 12, 5, 7, - 0, 9, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 12, - 12, 17, 7, 16, - }, - // 0b00110110 case 54 - { - 13, 14, 2, 10, - 0, 13, 2, 10, - 0, 10, 2, 8, - 0, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 17, - 8, 17, 5, 7, - 8, 17, 7, 16, - }, - // 0b00110111 case 55 - { - 13, 14, 2, 10, - 13, 2, 3, 10, - 13, 10, 3, 5, - 12, 13, 3, 5, - 12, 13, 5, 17, - 3, 12, 5, 7, - 12, 17, 5, 7, - 12, 17, 7, 16, - }, - // 0b00111000 case 56 - { - 15, 3, 2, 11, - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - }, - // 0b00111001 case 57 - { - 12, 0, 2, 9, - 15, 12, 2, 9, - 2, 15, 9, 11, - 15, 12, 9, 11, - 12, 9, 11, 7, - 12, 9, 7, 16, - 9, 7, 16, 5, - 9, 5, 16, 17, - }, - // 0b00111010 case 58 - { - 15, 3, 2, 11, - 0, 13, 1, 8, - 13, 1, 8, 7, - 13, 1, 7, 5, - 13, 7, 8, 16, - 13, 7, 16, 5, - 13, 5, 16, 17, - }, - // 0b00111011 case 59 - { - 12, 13, 1, 17, - 12, 17, 1, 5, - 12, 5, 1, 7, - 12, 17, 5, 7, - 12, 17, 7, 16, - 2, 12, 1, 7, - 15, 12, 2, 7, - 15, 7, 2, 11, - }, - // 0b00111100 case 60 - { - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - 14, 3, 1, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00111101 case 61 - { - 0, 9, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 16, - 0, 16, 7, 12, - 12, 0, 11, 7, - 14, 0, 1, 10, - 12, 0, 15, 11, - 14, 15, 0, 11, - 14, 11, 0, 10, - }, - // 0b00111110 case 62 - { - 15, 3, 0, 11, - 14, 15, 0, 11, - 14, 11, 0, 10, - 14, 0, 13, 10, - 0, 13, 10, 5, - 0, 13, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b00111111 case 63 - { - 12, 14, 15, 11, - 12, 14, 11, 10, - 12, 13, 14, 10, - 11, 12, 10, 7, - 12, 13, 10, 7, - 12, 13, 7, 16, - 13, 10, 7, 5, - 13, 5, 7, 17, - 13, 7, 16, 17, - }, - // 0b01000000 case 64 - {10, 6, 5, 18}, - // 0b01000001 case 65 - { - 12, 0, 3, 8, - 10, 6, 5, 18, - }, - // 0b01000010 case 66 - { - 0, 13, 1, 9, - 10, 6, 5, 18, - }, - // 0b01000011 case 67 - { - 10, 6, 5, 18, - 3, 12, 1, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - }, - // 0b01000100 case 68 - { - 1, 14, 2, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01000101 case 69 - { - 12, 0, 3, 8, - 14, 2, 1, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01000110 case 70 - { - 0, 13, 2, 6, - 0, 13, 6, 9, - 13, 14, 2, 6, - 13, 14, 6, 9, - 9, 14, 6, 5, - 14, 6, 5, 18, - }, - // 0b01000111 case 71 - { - 3, 12, 2, 8, - 12, 13, 2, 8, - 13, 2, 8, 9, - 13, 14, 2, 9, - 9, 2, 8, 5, - 9, 14, 2, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01001000 case 72 - { - 10, 6, 5, 18, - 15, 3, 2, 11, - }, - // 0b01001001 case 73 - { - 10, 6, 5, 18, - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - }, - // 0b01001010 case 74 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - 10, 6, 5, 18, - }, - // 0b01001011 case 75 - { - 10, 6, 5, 18, - 2, 15, 1, 11, - 15, 13, 1, 11, - 13, 1, 11, 9, - 15, 12, 13, 11, - 11, 12, 13, 9, - 11, 12, 9, 8, - }, - // 0b01001100 case 76 - { - 14, 15, 3, 11, - 1, 14, 3, 11, - 1, 11, 3, 5, - 1, 14, 11, 5, - 5, 14, 11, 6, - 5, 14, 6, 18, - }, - // 0b01001101 case 77 - { - 12, 0, 15, 8, - 15, 8, 0, 11, - 14, 0, 1, 5, - 14, 15, 0, 11, - 14, 0, 5, 6, - 14, 11, 0, 6, - 14, 6, 5, 18, - }, - // 0b01001110 case 78 - { - 0, 13, 14, 9, - 14, 15, 3, 11, - 14, 3, 0, 9, - 14, 11, 3, 6, - 14, 3, 9, 5, - 14, 6, 3, 5, - 14, 6, 5, 18, - }, - // 0b01001111 case 79 - { - 15, 12, 13, 8, - 13, 15, 8, 11, - 13, 11, 8, 9, - 13, 14, 15, 9, - 14, 15, 9, 11, - 9, 14, 11, 5, - 14, 11, 5, 6, - 14, 6, 5, 18, - }, - // 0b01010000 case 80 - { - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01010001 case 81 - { - 10, 6, 5, 18, - 12, 0, 3, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b01010010 case 82 - { - 13, 1, 0, 9, - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01010011 case 83 - { - 10, 6, 5, 18, - 12, 13, 1, 9, - 3, 12, 1, 9, - 3, 9, 1, 7, - 3, 12, 9, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - }, - // 0b01010100 case 84 - { - 8, 4, 7, 16, - 14, 2, 1, 6, - 1, 14, 6, 5, - 5, 14, 6, 18, - }, - // 0b01010101 case 85 - { - 3, 12, 0, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - 1, 14, 2, 5, - 14, 2, 5, 6, - 5, 14, 6, 18, - }, - // 0b01010110 case 86 - { - 8, 4, 7, 16, - 0, 13, 2, 6, - 0, 13, 6, 9, - 13, 14, 2, 6, - 13, 14, 6, 9, - 14, 6, 9, 5, - 14, 6, 5, 18, - }, - // 0b01010111 case 87 - { - 13, 2, 3, 9, - 13, 3, 12, 9, - 13, 14, 2, 9, - 14, 2, 9, 6, - 3, 12, 9, 7, - 12, 9, 7, 4, - 14, 6, 9, 5, - 12, 4, 7, 16, - 14, 6, 5, 18, - }, - // 0b01011000 case 88 - { - 8, 4, 7, 16, - 10, 6, 5, 18, - 15, 3, 2, 11, - }, - // 0b01011001 case 89 - { - 10, 6, 5, 18, - 2, 15, 0, 4, - 2, 15, 4, 11, - 15, 12, 0, 4, - 15, 12, 4, 11, - 11, 12, 4, 7, - 7, 12, 4, 16, - }, - // 0b01011010 case 90 - { - 13, 1, 0, 9, - 2, 15, 3, 11, - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01011011 case 91 - { - 10, 6, 5, 18, - 15, 1, 2, 11, - 15, 13, 1, 11, - 13, 1, 11, 9, - 15, 12, 13, 11, - 12, 13, 11, 9, - 12, 9, 11, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - }, - // 0b01011100 case 92 - { - 8, 4, 7, 16, - 1, 15, 3, 5, - 15, 3, 5, 6, - 15, 3, 6, 11, - 1, 14, 15, 6, - 1, 14, 6, 5, - 14, 6, 5, 18, - }, - // 0b01011101 case 93 - { - 15, 0, 1, 11, - 15, 12, 0, 11, - 1, 14, 15, 11, - 11, 12, 0, 4, - 11, 1, 14, 5, - 11, 12, 4, 7, - 11, 5, 14, 6, - 14, 6, 5, 18, - 12, 4, 7, 16, - }, - // 0b01011110 case 94 - { - 8, 4, 7, 16, - 13, 3, 0, 9, - 13, 15, 3, 9, - 15, 3, 9, 11, - 13, 14, 15, 9, - 14, 15, 9, 11, - 14, 11, 9, 5, - 14, 11, 5, 6, - 14, 6, 5, 18, - }, - // 0b01011111 case 95 - { - 15, 12, 13, 11, - 11, 12, 13, 9, - 11, 12, 9, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - 13, 14, 15, 9, - 14, 15, 9, 11, - 9, 14, 11, 5, - 5, 14, 11, 6, - 14, 6, 5, 18, - }, - // 0b01100000 case 96 - { - 9, 10, 4, 17, - 10, 6, 4, 17, - 10, 6, 17, 18, - }, - // 0b01100001 case 97 - { - 12, 0, 3, 8, - 4, 9, 6, 17, - 9, 10, 6, 17, - 17, 10, 6, 18, - }, - // 0b01100010 case 98 - { - 0, 13, 1, 6, - 1, 10, 6, 18, - 13, 1, 6, 18, - 0, 13, 6, 4, - 13, 18, 6, 4, - 13, 18, 4, 17, - }, - // 0b01100011 case 99 - { - 3, 12, 1, 8, - 12, 13, 1, 8, - 8, 13, 1, 17, - 1, 8, 17, 4, - 1, 6, 8, 4, - 1, 4, 17, 6, - 1, 6, 17, 10, - 17, 10, 6, 18, - }, - // 0b01100100 case 100 - { - 1, 14, 2, 6, - 1, 2, 4, 6, - 1, 14, 6, 18, - 1, 18, 6, 4, - 1, 18, 4, 9, - 9, 18, 4, 17, - }, - // 0b01100101 case 101 - { - 3, 12, 0, 8, - 1, 14, 2, 9, - 9, 14, 2, 4, - 14, 2, 4, 6, - 9, 14, 4, 17, - 14, 6, 4, 17, - 14, 6, 17, 18, - }, - // 0b01100110 case 102 - { - 0, 13, 2, 4, - 13, 14, 2, 4, - 14, 2, 4, 6, - 14, 18, 6, 4, - 14, 18, 4, 13, - 13, 18, 4, 17, - }, - // 0b01100111 case 103 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 13, 14, 2, 8, - 14, 2, 8, 4, - 13, 14, 8, 4, - 14, 2, 4, 6, - 13, 14, 4, 17, - 14, 4, 17, 6, - 14, 6, 17, 18, - }, - // 0b01101000 case 104 - { - 2, 15, 3, 11, - 4, 9, 6, 17, - 9, 10, 6, 17, - 10, 6, 17, 18, - }, - // 0b01101001 case 105 - { - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - 4, 9, 6, 17, - 9, 10, 6, 17, - 10, 6, 17, 18, - }, - // 0b01101010 case 106 - { - 2, 15, 3, 11, - 0, 13, 1, 6, - 0, 13, 6, 4, - 1, 10, 6, 4, - 13, 1, 4, 17, - 10, 6, 4, 18, - 17, 1, 4, 10, - 17, 10, 4, 18, - }, - // 0b01101011 case 107 - { - 15, 1, 2, 11, - 15, 12, 1, 11, - 12, 1, 11, 8, - 12, 13, 1, 8, - 8, 13, 1, 4, - 13, 1, 4, 17, - 1, 6, 4, 17, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01101100 case 108 - { - 1, 14, 3, 9, - 14, 15, 3, 9, - 15, 3, 9, 11, - 14, 15, 9, 11, - 14, 11, 9, 6, - 14, 6, 9, 18, - 9, 18, 6, 4, - 4, 9, 18, 17, - }, - // 0b01101101 case 109 - { - 12, 0, 1, 8, - 15, 12, 1, 8, - 15, 8, 1, 11, - 14, 15, 1, 11, - 1, 14, 11, 6, - 1, 14, 6, 18, - 1, 18, 6, 4, - 1, 18, 4, 17, - 1, 17, 4, 9, - }, - // 0b01101110 case 110 - { - 14, 15, 3, 11, - 0, 14, 3, 11, - 0, 13, 14, 11, - 0, 13, 11, 6, - 13, 14, 11, 6, - 13, 14, 6, 18, - 0, 13, 6, 4, - 13, 18, 6, 4, - 13, 18, 4, 17, - }, - // 0b01101111 case 111 - { - 15, 12, 13, 11, - 13, 14, 15, 11, - 12, 13, 11, 8, - 8, 13, 14, 4, - 14, 8, 4, 11, - 14, 11, 4, 6, - 13, 14, 4, 17, - 14, 4, 17, 6, - 14, 6, 17, 18, - }, - // 0b01110000 case 112 - { - 8, 9, 10, 7, - 9, 10, 7, 6, - 8, 9, 7, 16, - 9, 10, 6, 18, - 9, 7, 16, 17, - 9, 6, 7, 17, - 9, 18, 6, 17, - }, - // 0b01110001 case 113 - { - 12, 0, 3, 7, - 12, 0, 7, 16, - 0, 9, 10, 7, - 0, 9, 7, 16, - 9, 10, 16, 17, - 10, 7, 16, 17, - 10, 7, 17, 6, - 10, 6, 17, 18, - }, - // 0b01110010 case 114 - { - 0, 13, 1, 10, - 0, 13, 10, 8, - 13, 10, 8, 6, - 13, 6, 8, 7, - 13, 10, 6, 18, - 13, 7, 8, 16, - 13, 6, 7, 17, - 13, 18, 6, 17, - 13, 7, 16, 17, - }, - // 0b01110011 case 115 - { - 3, 12, 13, 7, - 12, 13, 7, 16, - 13, 1, 3, 7, - 13, 1, 16, 17, - 1, 7, 16, 6, - 1, 6, 16, 17, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01110100 case 116 - { - 1, 14, 2, 6, - 1, 14, 6, 18, - 1, 18, 6, 7, - 1, 8, 9, 16, - 1, 7, 8, 16, - 1, 18, 7, 16, - 1, 18, 16, 9, - 9, 18, 16, 17, - }, - // 0b01110101 case 117 - { - 3, 12, 0, 9, - 3, 12, 9, 7, - 12, 9, 7, 16, - 9, 7, 16, 17, - 9, 6, 7, 17, - 1, 14, 2, 9, - 14, 2, 9, 6, - 14, 6, 9, 17, - 14, 6, 17, 18, - }, - // 0b01110110 case 118 - { - 13, 14, 2, 6, - 0, 13, 2, 6, - 13, 14, 6, 18, - 0, 13, 18, 17, - 0, 17, 18, 6, - 0, 17, 6, 7, - 0, 17, 7, 16, - 0, 7, 8, 16, - }, - // 0b01110111 case 119 - { - 12, 2, 3, 7, - 12, 14, 2, 7, - 14, 2, 7, 6, - 12, 13, 14, 7, - 12, 13, 7, 16, - 14, 6, 7, 18, - 14, 18, 7, 16, - 13, 14, 16, 18, - 13, 18, 16, 17, - }, - // 0b01111000 case 120 - { - 2, 15, 3, 11, - 8, 9, 10, 7, - 9, 10, 7, 6, - 9, 10, 6, 18, - 8, 9, 7, 16, - 9, 18, 6, 17, - 9, 6, 7, 17, - 9, 7, 16, 17, - }, - // 0b01111001 case 121 - { - 15, 0, 2, 7, - 15, 7, 2, 11, - 15, 12, 0, 7, - 12, 0, 7, 16, - 16, 0, 7, 9, - 16, 9, 7, 17, - 9, 10, 7, 17, - 10, 7, 17, 18, - 10, 7, 18, 6, - }, - // 0b01111010 case 122 - { - 15, 3, 2, 11, - 0, 13, 1, 10, - 0, 13, 10, 8, - 13, 10, 8, 6, - 8, 13, 6, 7, - 13, 6, 7, 17, - 13, 10, 6, 17, - 13, 7, 8, 17, - 17, 10, 6, 18, - 17, 7, 8, 16, - }, - // 0b01111011 case 123 - { - 15, 1, 2, 11, - 15, 12, 1, 11, - 12, 13, 1, 11, - 13, 1, 11, 7, - 12, 13, 11, 7, - 12, 13, 7, 16, - 13, 7, 16, 17, - 13, 1, 7, 17, - 1, 7, 17, 6, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01111100 case 124 - { - 3, 11, 6, 15, - 1, 15, 3, 6, - 1, 14, 15, 6, - 1, 14, 6, 18, - 1, 18, 6, 9, - 9, 18, 6, 17, - 8, 9, 6, 17, - 8, 17, 6, 7, - 8, 17, 7, 16, - }, - // 0b01111101 case 125 - { - 12, 0, 1, 9, - 12, 1, 14, 9, - 12, 14, 15, 9, - 12, 9, 15, 17, - 14, 15, 9, 17, - 15, 12, 17, 16, - 15, 17, 14, 18, - 15, 16, 17, 7, - 15, 17, 18, 6, - 15, 7, 17, 11, - 15, 17, 6, 11, - 11, 6, 7, 17, - }, - // 0b01111110 case 126 - { - 15, 3, 0, 11, - 14, 15, 0, 11, - 0, 14, 11, 6, - 0, 13, 14, 6, - 13, 14, 6, 18, - 0, 13, 18, 17, - 0, 18, 6, 17, - 0, 17, 6, 7, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b01111111 case 127 - { - 6, 7, 11, 15, - 12, 13, 15, 7, - 13, 14, 15, 7, - 14, 15, 7, 6, - 13, 14, 7, 6, - 13, 14, 6, 18, - 12, 13, 7, 16, - 13, 18, 6, 17, - 13, 6, 7, 17, - 13, 7, 16, 17, - }, - // 0b10000000 case 128 - { - 11, 7, 6, 19, - }, - // 0b10000001 case 129 - { - 3, 12, 0, 8, - 11, 7, 6, 19, - }, - // 0b10000010 case 130 - { - 0, 13, 1, 9, - 11, 7, 6, 19, - }, - // 0b10000011 case 131 - { - 11, 7, 6, 19, - 3, 12, 1, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - }, - // 0b10000100 case 132 - { - 1, 14, 2, 10, - 11, 7, 6, 19, - }, - // 0b10000101 case 133 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 11, 7, 6, 19, - }, - // 0b10000110 case 134 - { - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 10, - 11, 7, 6, 19, - }, - // 0b10000111 case 135 - { - 12, 2, 3, 8, - 12, 14, 2, 8, - 14, 2, 8, 10, - 12, 13, 14, 8, - 13, 14, 8, 10, - 13, 10, 8, 9, - 11, 7, 6, 19, - }, - // 0b10001000 case 136 - { - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001001 case 137 - { - 2, 15, 0, 6, - 15, 12, 0, 6, - 12, 0, 6, 7, - 12, 0, 7, 8, - 15, 12, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001010 case 138 - { - 0, 13, 1, 9, - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001011 case 139 - { - 12, 13, 1, 9, - 12, 9, 1, 8, - 12, 1, 2, 8, - 2, 8, 1, 7, - 2, 7, 1, 6, - 2, 15, 12, 8, - 2, 15, 8, 7, - 2, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10001100 case 140 - { - 15, 3, 1, 7, - 14, 15, 1, 7, - 1, 14, 7, 6, - 1, 14, 6, 10, - 14, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10001101 case 141 - { - 14, 0, 1, 10, - 14, 12, 0, 10, - 12, 0, 10, 8, - 14, 15, 12, 10, - 15, 12, 10, 8, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - }, - // 0b10001110 case 142 - { - 0, 13, 14, 9, - 14, 0, 9, 10, - 14, 15, 0, 10, - 15, 3, 0, 10, - 10, 3, 0, 7, - 10, 15, 3, 7, - 10, 15, 7, 6, - 6, 15, 7, 19, - }, - // 0b10001111 case 143 - { - 14, 15, 12, 8, - 14, 15, 8, 10, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - 12, 13, 14, 10, - 12, 13, 10, 8, - 8, 13, 10, 9, - }, - // 0b10010000 case 144 - { - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010001 case 145 - { - 3, 12, 0, 4, - 3, 4, 0, 6, - 12, 4, 6, 16, - 3, 12, 6, 16, - 3, 16, 6, 19, - 3, 19, 6, 11, - }, - // 0b10010010 case 146 - { - 0, 13, 1, 9, - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010011 case 147 - { - 3, 13, 1, 9, - 3, 12, 13, 9, - 3, 12, 9, 6, - 12, 9, 6, 4, - 3, 12, 4, 16, - 3, 16, 4, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10010100 case 148 - { - 1, 14, 2, 10, - 11, 8, 6, 19, - 8, 4, 6, 19, - 8, 4, 19, 16, - }, - // 0b10010101 case 149 - { - 1, 14, 2, 10, - 3, 12, 0, 11, - 12, 0, 11, 6, - 12, 6, 11, 19, - 0, 6, 19, 4, - 12, 0, 19, 4, - 12, 4, 19, 16, - }, - // 0b10010110 case 150 - { - 13, 14, 0, 9, - 14, 2, 0, 9, - 14, 2, 9, 10, - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010111 case 151 - { - 3, 14, 2, 10, - 3, 13, 14, 10, - 3, 13, 10, 9, - 3, 12, 13, 9, - 3, 12, 9, 4, - 3, 12, 4, 16, - 3, 16, 4, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10011000 case 152 - { - 2, 15, 3, 8, - 2, 15, 8, 4, - 15, 8, 4, 16, - 2, 15, 4, 6, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011001 case 153 - { - 12, 0, 2, 4, - 15, 12, 2, 4, - 2, 15, 4, 6, - 12, 4, 15, 16, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011010 case 154 - { - 0, 13, 1, 9, - 2, 15, 3, 8, - 2, 15, 8, 4, - 15, 8, 4, 16, - 2, 15, 4, 6, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011011 case 155 - { - 2, 13, 1, 9, - 2, 13, 9, 4, - 12, 13, 2, 4, - 15, 12, 2, 4, - 2, 15, 4, 6, - 15, 12, 4, 16, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011100 case 156 - { - 14, 3, 1, 8, - 14, 8, 1, 10, - 14, 15, 3, 8, - 14, 15, 8, 10, - 10, 15, 8, 6, - 15, 8, 6, 19, - 6, 19, 8, 4, - 19, 8, 4, 16, - }, - // 0b10011101 case 157 - { - 14, 0, 1, 10, - 14, 15, 0, 10, - 15, 12, 0, 10, - 12, 0, 10, 6, - 15, 12, 10, 6, - 12, 0, 6, 4, - 15, 12, 6, 19, - 12, 4, 6, 19, - 12, 4, 19, 16, - }, - // 0b10011110 case 158 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 10, - 14, 15, 3, 10, - 15, 3, 10, 6, - 15, 3, 6, 19, - 3, 6, 19, 4, - 3, 4, 19, 8, - 8, 4, 19, 16, - }, - // 0b10011111 case 159 - { - 12, 13, 14, 10, - 12, 13, 10, 9, - 12, 14, 15, 10, - 15, 9, 10, 6, - 15, 12, 9, 6, - 12, 9, 6, 4, - 15, 12, 6, 19, - 12, 6, 19, 4, - 12, 4, 19, 16, - }, - // 0b10100000 case 160 - { - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100001 case 161 - { - 3, 12, 0, 8, - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100010 case 162 - { - 0, 13, 1, 4, - 13, 1, 4, 5, - 4, 13, 5, 17, - 11, 7, 6, 19, - }, - // 0b10100011 case 163 - { - 3, 13, 1, 5, - 3, 12, 13, 5, - 12, 13, 5, 17, - 3, 17, 5, 4, - 3, 12, 17, 4, - 3, 12, 4, 8, - 11, 7, 6, 19, - }, - // 0b10100100 case 164 - { - 1, 14, 2, 10, - 11, 7, 6, 19, - 9, 5, 4, 17, - }, - // 0b10100101 case 165 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100110 case 166 - { - 14, 2, 0, 10, - 13, 14, 0, 10, - 0, 13, 10, 5, - 0, 13, 5, 4, - 13, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100111 case 167 - { - 11, 7, 6, 19, - 3, 14, 2, 10, - 3, 12, 14, 10, - 3, 12, 10, 8, - 12, 13, 14, 10, - 12, 13, 10, 8, - 8, 13, 10, 5, - 8, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b10101000 case 168 - { - 9, 5, 4, 17, - 2, 15, 3, 6, - 15, 3, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101001 case 169 - { - 9, 5, 4, 17, - 2, 12, 0, 6, - 12, 0, 6, 7, - 12, 0, 7, 8, - 2, 15, 12, 6, - 15, 12, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101010 case 170 - { - 0, 13, 1, 4, - 13, 1, 4, 5, - 13, 5, 4, 17, - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10101011 case 171 - { - 2, 12, 1, 8, - 12, 13, 1, 8, - 2, 15, 12, 8, - 8, 13, 1, 5, - 8, 13, 5, 4, - 4, 13, 5, 17, - 2, 15, 8, 6, - 15, 8, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101100 case 172 - { - 9, 5, 4, 17, - 1, 15, 3, 7, - 1, 14, 15, 7, - 1, 14, 7, 6, - 1, 14, 6, 10, - 14, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10101101 case 173 - { - 9, 5, 4, 17, - 1, 12, 0, 8, - 14, 12, 1, 8, - 14, 15, 12, 8, - 14, 8, 1, 10, - 14, 15, 8, 10, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - }, - // 0b10101110 case 174 - { - 13, 14, 0, 10, - 14, 3, 0, 10, - 14, 15, 3, 10, - 0, 13, 10, 5, - 0, 5, 10, 4, - 0, 13, 5, 4, - 13, 5, 4, 17, - 15, 3, 10, 7, - 15, 7, 10, 6, - 15, 7, 6, 19, - }, - // 0b10101111 case 175 - { - 12, 13, 14, 10, - 12, 14, 15, 10, - 12, 13, 10, 8, - 10, 15, 12, 8, - 10, 15, 8, 6, - 15, 8, 6, 7, - 15, 7, 6, 19, - 13, 10, 8, 4, - 13, 10, 4, 5, - 13, 5, 4, 17, - }, - // 0b10110000 case 176 - { - 11, 8, 9, 5, - 11, 8, 5, 6, - 8, 9, 5, 17, - 8, 6, 11, 19, - 8, 17, 5, 16, - 8, 5, 6, 16, - 8, 6, 19, 16, - }, - // 0b10110001 case 177 - { - 12, 0, 3, 11, - 11, 12, 0, 9, - 11, 12, 9, 6, - 12, 9, 6, 5, - 12, 6, 11, 19, - 12, 9, 5, 17, - 12, 17, 5, 16, - 12, 5, 6, 16, - 12, 6, 19, 16, - }, - // 0b10110010 case 178 - { - 0, 13, 1, 5, - 0, 13, 5, 17, - 0, 17, 5, 6, - 0, 17, 6, 11, - 11, 17, 6, 19, - 0, 17, 11, 19, - 0, 19, 11, 8, - 0, 17, 19, 8, - 8, 17, 19, 16, - }, - // 0b10110011 case 179 - { - 3, 13, 1, 5, - 3, 12, 13, 5, - 12, 13, 5, 17, - 3, 12, 17, 16, - 3, 17, 5, 16, - 3, 16, 5, 6, - 3, 16, 6, 11, - 16, 6, 11, 19, - }, - // 0b10110100 case 180 - { - 11, 8, 9, 5, - 11, 8, 5, 6, - 8, 9, 5, 17, - 8, 17, 5, 16, - 8, 5, 6, 16, - 8, 6, 11, 19, - 8, 6, 19, 16, - 1, 14, 2, 10, - }, - // 0b10110101 case 181 - { - 1, 14, 2, 10, - 3, 12, 0, 9, - 3, 12, 9, 11, - 11, 12, 9, 5, - 11, 12, 5, 6, - 12, 9, 5, 17, - 11, 12, 6, 19, - 12, 17, 5, 16, - 12, 5, 6, 16, - 12, 6, 19, 16, - }, - // 0b10110110 case 182 - { - 13, 14, 2, 10, - 0, 13, 2, 10, - 0, 10, 2, 5, - 0, 13, 10, 5, - 0, 13, 5, 17, - 0, 17, 5, 8, - 8, 17, 5, 16, - 11, 8, 5, 16, - 11, 16, 5, 6, - 11, 16, 6, 19, - }, - // 0b10110111 case 183 - { - 3, 14, 2, 10, - 3, 13, 14, 10, - 3, 12, 13, 10, - 3, 12, 10, 5, - 12, 13, 10, 5, - 12, 13, 5, 17, - 3, 12, 17, 16, - 3, 17, 5, 16, - 3, 16, 5, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10111000 case 184 - { - 8, 9, 5, 17, - 8, 17, 5, 16, - 2, 15, 3, 8, - 2, 15, 8, 5, - 2, 15, 5, 6, - 15, 8, 5, 6, - 6, 8, 5, 16, - 6, 15, 8, 19, - 6, 19, 8, 16, - }, - // 0b10111001 case 185 - { - 2, 15, 0, 6, - 15, 12, 0, 6, - 15, 12, 6, 19, - 12, 0, 19, 16, - 0, 6, 19, 16, - 0, 6, 16, 5, - 0, 5, 16, 9, - 16, 9, 5, 17, - }, - // 0b10111010 case 186 - { - 0, 13, 1, 8, - 13, 1, 8, 5, - 8, 13, 5, 17, - 8, 17, 5, 16, - 8, 16, 5, 6, - 2, 15, 3, 8, - 2, 15, 8, 6, - 15, 8, 6, 16, - 15, 16, 6, 19, - }, - // 0b10111011 case 187 - { - 2, 13, 1, 5, - 2, 12, 13, 5, - 12, 13, 5, 17, - 12, 17, 5, 16, - 12, 2, 15, 5, - 2, 15, 5, 6, - 15, 12, 5, 16, - 15, 16, 5, 6, - 15, 16, 6, 19, - }, - // 0b10111100 case 188 - { - 14, 3, 1, 6, - 1, 14, 6, 10, - 14, 15, 3, 6, - 15, 3, 6, 19, - 3, 6, 19, 8, - 8, 6, 19, 16, - 8, 6, 16, 9, - 9, 6, 16, 5, - 9, 5, 16, 17, - }, - // 0b10111101 case 189 - { - 14, 0, 1, 10, - 14, 12, 0, 10, - 14, 15, 12, 10, - 12, 0, 10, 6, - 10, 15, 12, 6, - 6, 15, 12, 19, - 12, 0, 19, 16, - 0, 6, 19, 16, - 0, 6, 16, 5, - 0, 5, 16, 9, - 16, 9, 5, 17, - }, - // 0b10111110 case 190 - { - 0, 15, 3, 8, - 0, 14, 15, 8, - 0, 13, 14, 8, - 8, 14, 15, 16, - 14, 15, 16, 19, - 13, 14, 8, 16, - 13, 14, 16, 17, - 14, 16, 17, 5, - 14, 16, 5, 10, - 10, 16, 5, 6, - 14, 19, 16, 10, - 10, 19, 16, 6, - }, - // 0b10111111 case 191 - { - 13, 15, 12, 16, - 13, 14, 15, 16, - 13, 14, 16, 17, - 14, 15, 16, 19, - 14, 16, 17, 5, - 14, 19, 16, 6, - 14, 6, 16, 10, - 14, 16, 5, 10, - 10, 6, 16, 5, - }, - // 0b11000000 case 192 - { - 10, 11, 5, 18, - 18, 11, 5, 7, - 11, 7, 18, 19, - }, - // 0b11000001 case 193 - { - 3, 12, 0, 8, - 5, 10, 11, 18, - 5, 18, 11, 7, - 11, 7, 18, 19, - }, - // 0b11000010 case 194 - { - 0, 13, 1, 9, - 10, 11, 5, 18, - 11, 7, 5, 18, - 11, 7, 18, 19, - }, - // 0b11000011 case 195 - { - 12, 1, 3, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - 10, 11, 5, 18, - 11, 7, 5, 18, - 11, 7, 18, 19, - }, - // 0b11000100 case 196 - { - 1, 14, 2, 7, - 1, 14, 7, 5, - 14, 2, 5, 18, - 2, 7, 5, 18, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11000101 case 197 - { - 1, 14, 2, 7, - 1, 14, 7, 5, - 14, 2, 5, 18, - 2, 7, 5, 18, - 2, 7, 18, 11, - 11, 7, 18, 19, - 3, 12, 0, 8, - }, - // 0b11000110 case 198 - { - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 5, - 14, 2, 5, 18, - 2, 9, 5, 7, - 2, 5, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11000111 case 199 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 8, 13, 2, 9, - 13, 14, 2, 9, - 9, 14, 2, 5, - 14, 2, 5, 18, - 2, 5, 18, 7, - 7, 18, 2, 11, - 18, 11, 7, 19, - }, - // 0b11001000 case 200 - { - 2, 15, 3, 10, - 15, 3, 10, 5, - 5, 10, 15, 18, - 5, 15, 3, 7, - 5, 18, 15, 7, - 18, 15, 7, 19, - }, - // 0b11001001 case 201 - { - 12, 0, 2, 8, - 15, 12, 2, 8, - 2, 15, 8, 7, - 2, 15, 7, 19, - 2, 7, 8, 5, - 2, 19, 7, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001010 case 202 - { - 0, 13, 1, 9, - 2, 15, 3, 5, - 15, 3, 5, 7, - 2, 15, 7, 19, - 2, 7, 5, 19, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001011 case 203 - { - 2, 13, 1, 9, - 2, 12, 13, 9, - 2, 12, 9, 8, - 2, 15, 12, 8, - 2, 15, 8, 7, - 2, 15, 7, 19, - 2, 19, 7, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001100 case 204 - { - 1, 14, 3, 5, - 14, 15, 3, 5, - 15, 3, 5, 7, - 14, 15, 5, 18, - 15, 7, 5, 18, - 15, 7, 18, 19, - }, - // 0b11001101 case 205 - { - 1, 12, 0, 8, - 1, 15, 12, 8, - 1, 15, 8, 7, - 1, 14, 15, 7, - 14, 15, 7, 19, - 14, 7, 1, 5, - 14, 7, 5, 19, - 14, 19, 5, 18, - }, - // 0b11001110 case 206 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 5, - 14, 15, 3, 5, - 14, 15, 5, 18, - 15, 3, 5, 7, - 15, 7, 5, 18, - 15, 7, 18, 19, - }, - // 0b11001111 case 207 - { - 15, 12, 13, 8, - 13, 15, 8, 9, - 14, 15, 13, 9, - 15, 8, 9, 7, - 14, 15, 9, 7, - 14, 7, 9, 5, - 15, 7, 14, 19, - 14, 19, 7, 5, - 14, 19, 5, 18, - }, - // 0b11010000 case 208 - { - 10, 11, 8, 4, - 10, 11, 4, 5, - 11, 8, 4, 16, - 11, 5, 10, 18, - 11, 16, 4, 19, - 11, 4, 5, 19, - 11, 5, 18, 19, - }, - // 0b11010001 case 209 - { - 3, 12, 0, 5, - 12, 0, 5, 4, - 12, 4, 5, 16, - 3, 12, 5, 16, - 3, 16, 5, 11, - 11, 16, 5, 19, - 11, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11010010 case 210 - { - 0, 13, 1, 9, - 10, 11, 8, 4, - 10, 11, 4, 5, - 10, 11, 5, 18, - 11, 8, 4, 16, - 11, 5, 18, 19, - 11, 4, 5, 19, - 11, 16, 4, 19, - }, - // 0b11010011 case 211 - { - 3, 13, 1, 4, - 13, 1, 4, 9, - 3, 12, 13, 4, - 3, 12, 4, 16, - 3, 16, 4, 11, - 11, 16, 4, 19, - 10, 11, 4, 19, - 10, 19, 4, 5, - 10, 19, 5, 18, - }, - // 0b11010100 case 212 - { - 1, 14, 2, 5, - 14, 2, 5, 18, - 2, 5, 18, 4, - 2, 4, 18, 8, - 2, 8, 18, 11, - 18, 8, 4, 16, - 18, 8, 16, 11, - 18, 11, 16, 19, - }, - // 0b11010101 case 213 - { - 12, 0, 3, 11, - 12, 0, 11, 4, - 12, 4, 11, 16, - 4, 11, 16, 19, - 11, 19, 4, 5, - 11, 19, 5, 18, - 1, 14, 2, 11, - 1, 14, 11, 5, - 14, 11, 5, 18, - }, - // 0b11010110 case 214 - { - 13, 2, 0, 5, - 0, 13, 5, 9, - 13, 14, 2, 5, - 5, 14, 2, 18, - 5, 18, 2, 11, - 5, 18, 11, 19, - 5, 11, 8, 19, - 8, 5, 19, 4, - 8, 4, 19, 16, - }, - // 0b11010111 case 215 - { - 3, 2, 11, 19, - 3, 14, 2, 19, - 3, 12, 14, 19, - 12, 13, 14, 19, - 12, 13, 19, 16, - 13, 14, 16, 9, - 9, 14, 16, 4, - 14, 19, 16, 4, - 14, 4, 9, 5, - 14, 19, 4, 5, - 14, 19, 5, 18, - }, - // 0b11011000 case 216 - { - 2, 15, 3, 10, - 15, 3, 10, 8, - 10, 15, 8, 5, - 15, 8, 5, 4, - 15, 5, 10, 18, - 15, 8, 4, 16, - 15, 4, 5, 19, - 15, 16, 4, 19, - 15, 5, 18, 19, - }, - // 0b11011001 case 217 - { - 2, 12, 0, 4, - 2, 15, 12, 4, - 15, 12, 4, 16, - 2, 15, 16, 19, - 2, 19, 16, 4, - 2, 19, 4, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11011010 case 218 - { - 0, 13, 1, 9, - 2, 15, 3, 10, - 15, 3, 10, 8, - 10, 15, 8, 5, - 5, 15, 8, 4, - 15, 5, 10, 18, - 15, 4, 5, 19, - 15, 8, 4, 16, - 15, 5, 18, 19, - 15, 16, 4, 19, - }, - // 0b11011011 case 219 - { - 13, 1, 2, 9, - 12, 13, 2, 9, - 12, 2, 15, 9, - 15, 9, 2, 4, - 15, 12, 9, 4, - 15, 12, 4, 16, - 15, 16, 2, 19, - 2, 16, 4, 19, - 2, 19, 4, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11011100 case 220 - { - 1, 14, 3, 5, - 14, 15, 3, 5, - 14, 15, 5, 18, - 15, 3, 5, 8, - 15, 8, 5, 4, - 15, 8, 4, 16, - 15, 16, 4, 19, - 15, 4, 5, 19, - 15, 5, 18, 19, - }, - // 0b11011101 case 221 - { - 14, 0, 1, 5, - 14, 15, 0, 5, - 14, 15, 5, 18, - 15, 12, 0, 5, - 12, 0, 5, 4, - 15, 12, 18, 19, - 12, 4, 5, 16, - 12, 5, 18, 16, - 12, 18, 19, 16, - }, - // 0b11011110 case 222 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 5, - 14, 3, 5, 18, - 14, 15, 3, 18, - 15, 3, 18, 19, - 3, 18, 19, 5, - 3, 5, 19, 4, - 3, 4, 19, 8, - 8, 4, 19, 16, - }, - // 0b11011111 case 223 - { - 14, 12, 13, 9, - 14, 15, 12, 9, - 14, 15, 9, 5, - 14, 15, 5, 18, - 15, 9, 5, 4, - 15, 12, 9, 4, - 15, 12, 4, 16, - 15, 16, 4, 19, - 15, 4, 5, 19, - 15, 5, 18, 19, - }, - // 0b11100000 case 224 - { - 9, 10, 11, 7, - 9, 10, 7, 4, - 10, 11, 7, 19, - 10, 4, 9, 17, - 10, 19, 7, 18, - 10, 7, 4, 18, - 10, 4, 17, 18, - }, - // 0b11100001 case 225 - { - 3, 12, 0, 8, - 9, 10, 11, 7, - 9, 10, 7, 4, - 10, 11, 7, 19, - 10, 4, 9, 17, - 10, 19, 7, 18, - 10, 7, 4, 18, - 10, 4, 17, 18, - }, - // 0b11100010 case 226 - { - 0, 13, 1, 4, - 13, 1, 4, 17, - 1, 4, 17, 10, - 10, 4, 17, 18, - 1, 4, 10, 11, - 10, 11, 4, 18, - 18, 11, 4, 7, - 18, 11, 7, 19, - }, - // 0b11100011 case 227 - { - 12, 1, 3, 4, - 12, 4, 3, 8, - 12, 13, 1, 4, - 13, 1, 4, 17, - 1, 4, 17, 10, - 10, 4, 17, 18, - 10, 11, 4, 18, - 11, 4, 18, 7, - 11, 7, 18, 19, - }, - // 0b11100100 case 228 - { - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 4, - 14, 11, 4, 7, - 14, 11, 7, 19, - 14, 4, 9, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - }, - // 0b11100101 case 229 - { - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 4, - 14, 11, 4, 7, - 14, 11, 7, 19, - 14, 4, 9, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - 3, 12, 0, 8, - }, - // 0b11100110 case 230 - { - 0, 13, 2, 4, - 13, 14, 2, 4, - 13, 14, 4, 17, - 14, 2, 17, 18, - 2, 4, 17, 18, - 2, 4, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11100111 case 231 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 13, 2, 8, 4, - 13, 14, 2, 4, - 13, 14, 4, 17, - 14, 2, 17, 18, - 2, 4, 17, 18, - 2, 4, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11101000 case 232 - { - 2, 15, 3, 7, - 2, 15, 7, 19, - 2, 19, 7, 4, - 2, 19, 4, 9, - 9, 19, 4, 17, - 2, 19, 9, 10, - 9, 10, 19, 17, - 10, 19, 17, 18, - }, - // 0b11101001 case 233 - { - 2, 12, 0, 7, - 12, 0, 7, 8, - 2, 15, 12, 7, - 2, 15, 7, 19, - 2, 19, 7, 10, - 10, 19, 7, 18, - 9, 10, 7, 18, - 9, 18, 7, 4, - 9, 18, 4, 17, - }, - // 0b11101010 case 234 - { - 0, 13, 1, 10, - 0, 13, 10, 17, - 0, 17, 10, 4, - 10, 4, 17, 18, - 10, 7, 4, 18, - 2, 15, 3, 10, - 15, 3, 10, 7, - 10, 15, 7, 18, - 15, 7, 18, 19, - }, - // 0b11101011 case 235 - { - 13, 1, 2, 10, - 13, 2, 15, 10, - 13, 15, 12, 10, - 12, 13, 10, 18, - 10, 15, 12, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 8, - 12, 18, 19, 8, - 8, 17, 18, 4, - 8, 4, 18, 7, - 19, 8, 18, 7, - }, - // 0b11101100 case 236 - { - 1, 15, 3, 7, - 1, 14, 15, 7, - 14, 15, 7, 19, - 1, 14, 19, 18, - 1, 18, 19, 7, - 1, 18, 7, 4, - 1, 18, 4, 9, - 9, 18, 4, 17, - }, - // 0b11101101 case 237 - { - 1, 12, 0, 8, - 1, 15, 12, 8, - 1, 14, 15, 8, - 1, 14, 8, 7, - 14, 15, 8, 7, - 14, 15, 7, 19, - 1, 14, 19, 18, - 1, 18, 19, 7, - 1, 18, 7, 4, - 4, 1, 18, 9, - 9, 18, 4, 17, - }, - // 0b11101110 case 238 - { - 13, 3, 0, 4, - 13, 15, 3, 4, - 15, 3, 4, 7, - 13, 14, 15, 7, - 13, 14, 7, 4, - 14, 15, 7, 19, - 13, 14, 4, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - }, - // 0b11101111 case 239 - { - 14, 15, 12, 18, - 12, 13, 14, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 8, - 12, 18, 19, 8, - 8, 17, 18, 4, - 18, 8, 4, 7, - 19, 8, 18, 7, - }, - // 0b11110000 case 240 - { - 9, 10, 11, 18, - 8, 9, 11, 18, - 8, 9, 18, 17, - 18, 11, 8, 19, - 8, 17, 18, 16, - 8, 18, 19, 16, - }, - // 0b11110001 case 241 - { - 3, 12, 0, 11, - 12, 0, 11, 9, - 11, 12, 9, 16, - 9, 10, 11, 16, - 10, 11, 16, 19, - 9, 10, 16, 17, - 10, 19, 16, 18, - 10, 16, 17, 18, - }, - // 0b11110010 case 242 - { - 0, 13, 1, 10, - 0, 13, 10, 8, - 8, 13, 10, 17, - 8, 17, 10, 18, - 8, 17, 18, 16, - 11, 8, 10, 16, - 11, 16, 10, 18, - 11, 16, 18, 19, - }, - // 0b11110011 case 243 - { - 12, 1, 3, 11, - 12, 13, 1, 11, - 13, 1, 11, 10, - 11, 13, 10, 18, - 11, 13, 18, 19, - 12, 13, 11, 19, - 12, 13, 18, 17, - 12, 17, 18, 19, - 12, 17, 19, 16, - }, - // 0b11110100 case 244 - { - 1, 14, 2, 11, - 1, 14, 11, 9, - 14, 11, 9, 18, - 11, 9, 18, 19, - 9, 18, 19, 17, - 8, 9, 11, 19, - 8, 9, 19, 17, - 8, 17, 19, 16, - }, - // 0b11110101 case 245 - { - 3, 12, 0, 11, - 12, 0, 11, 9, - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 18, - 12, 9, 11, 19, - 9, 18, 11, 19, - 12, 9, 19, 16, - 9, 18, 19, 17, - 9, 19, 16, 17, - }, - // 0b11110110 case 246 - { - 0, 13, 2, 8, - 13, 2, 8, 11, - 13, 14, 2, 11, - 13, 14, 11, 19, - 13, 11, 8, 19, - 13, 19, 8, 16, - 13, 14, 19, 18, - 13, 19, 16, 17, - 13, 18, 19, 17, - }, - // 0b11110111 case 247 - { - 12, 2, 3, 11, - 12, 14, 2, 11, - 12, 13, 14, 11, - 13, 14, 11, 18, - 12, 13, 11, 18, - 12, 18, 11, 19, - 12, 13, 18, 17, - 12, 18, 19, 16, - 12, 17, 18, 16, - }, - // 0b11111000 case 248 - { - 2, 15, 3, 10, - 15, 3, 10, 8, - 15, 8, 10, 19, - 8, 10, 19, 16, - 16, 10, 19, 18, - 8, 9, 10, 16, - 16, 9, 10, 18, - 9, 18, 16, 17, - }, - // 0b11111001 case 249 - { - 2, 15, 0, 10, - 15, 12, 0, 10, - 12, 0, 10, 9, - 10, 15, 9, 18, - 15, 12, 9, 18, - 12, 9, 18, 17, - 18, 15, 12, 19, - 12, 17, 18, 19, - 12, 17, 19, 16, - }, - // 0b11111010 case 250 - { - 0, 13, 1, 8, - 13, 1, 8, 10, - 8, 13, 10, 16, - 13, 10, 16, 18, - 13, 18, 16, 17, - 2, 15, 3, 10, - 15, 3, 10, 8, - 15, 8, 10, 18, - 15, 8, 18, 16, - 15, 16, 18, 19, - }, - // 0b11111011 case 251 - { - 2, 1, 10, 18, - 2, 15, 1, 18, - 15, 13, 1, 18, - 15, 12, 13, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 16, - 12, 18, 19, 16, - }, - // 0b11111100 case 252 - { - 1, 14, 3, 9, - 14, 3, 9, 8, - 14, 15, 3, 8, - 9, 14, 8, 17, - 14, 15, 8, 17, - 17, 15, 8, 16, - 14, 15, 17, 18, - 15, 17, 18, 19, - 15, 16, 17, 19, - }, - // 0b11111101 case 253 - { - 1, 0, 9, 17, - 14, 0, 1, 17, - 14, 12, 0, 17, - 14, 15, 12, 17, - 14, 15, 17, 18, - 15, 12, 17, 16, - 15, 17, 18, 19, - 15, 16, 17, 19, - }, - // 0b11111110 case 254 - { - 0, 3, 8, 16, - 13, 3, 0, 16, - 13, 15, 3, 16, - 13, 14, 15, 16, - 13, 14, 16, 17, - 14, 15, 16, 19, - 14, 16, 17, 18, - 14, 19, 16, 18, - }, - // 0b11111111 case 255 - { - 12, 14, 15, 19, - 12, 13, 14, 19, - 12, 13, 19, 16, - 13, 14, 19, 18, - 13, 18, 19, 17, - 13, 19, 16, 17, - }, + output <- marchingCubesFE(s, bb, meshInc, r.order, r.shape) } //----------------------------------------------------------------------------- diff --git a/render/marchfehelper.go b/render/marchfehelper.go new file mode 100644 index 000000000..2948f7c52 --- /dev/null +++ b/render/marchfehelper.go @@ -0,0 +1,2855 @@ +package render + +import ( + "math" + "sync" + + "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" +) + +//----------------------------------------------------------------------------- + +// 3D print slicing is done along Z direction. +// Therefore, our slices are in XY plane. +type layerXY struct { + base v3.Vec // base coordinate of layer + inc v3.Vec // dx, dy, dz for each step + steps v3i.Vec // number of x,y,z steps + val0 []float64 // SDF values for z layer + val1 []float64 // SDF values for z + dz layer +} + +func newLayerXY(base, inc v3.Vec, steps v3i.Vec) *layerXY { + return &layerXY{base, inc, steps, nil, nil} +} + +// Evaluate the SDF for a given XY layer +func (l *layerXY) Evaluate(s sdf.SDF3, z int) { + + // Swap the layers + l.val0, l.val1 = l.val1, l.val0 + + nx, ny := l.steps.X, l.steps.Y + dx, dy, dz := l.inc.X, l.inc.Y, l.inc.Z + + // allocate storage + if l.val1 == nil { + l.val1 = make([]float64, (nx+1)*(ny+1)) + } + + // setup the loop variables + var p v3.Vec + p.Z = l.base.Z + float64(z)*dz + + // define the base struct for requesting evaluation + eReq := evalReq{ + wg: new(sync.WaitGroup), + fn: s.Evaluate, + out: l.val1, + } + + // evaluate the layer + p.X = l.base.X + + // Performance doesn't seem to improve past 100. + const batchSize = 100 + + eReq.p = make([]v3.Vec, 0, batchSize) + for x := 0; x < nx+1; x++ { + p.Y = l.base.Y + for y := 0; y < ny+1; y++ { + eReq.p = append(eReq.p, p) + if len(eReq.p) == batchSize { + eReq.wg.Add(1) + evalProcessCh <- eReq + eReq.out = eReq.out[batchSize:] // shift the output slice for processing + eReq.p = make([]v3.Vec, 0, batchSize) // create a new slice for the next batch + } + p.Y += dy + } + p.X += dx + } + + // send any remaining points for processing + if len(eReq.p) > 0 { + eReq.wg.Add(1) + evalProcessCh <- eReq + } + + // Wait for all processing to complete before returning + eReq.wg.Wait() +} + +func (l *layerXY) Get(x, y, z int) float64 { + idz := x*(l.steps.Y+1) + y + if z == 0 { + return l.val0[idz] + } + return l.val1[idz] +} + +//----------------------------------------------------------------------------- + +// Specify the point to create the tetrahedra. +// Point can be on edges or corners. +// Index from 0 to 11 means an edge. +// Index from 12 to 19 means a corner. +// Corners were originally indexed from 0 to 7 but they are shifted by 12. +// So, corners are from 0+12 to 7+12 i.e. from 12 to 19. +func point(edges [12]v3.Vec, corners [8]v3.Vec, index int) v3.Vec { + if 0 <= index && index < 12 { + return edges[index] + } else if index < 20 { + return corners[index-12] + } else { + // Should never reach here. + return v3.Vec{} + } +} + +//----------------------------------------------------------------------------- + +// Is a tetrahedron almost flat? +// To avoid mathematical problem while FEA is run. +// MATHEMATICA script is available here: +// https://math.stackexchange.com/a/4709610/197913 +func almostFlat(a, b, c, d v3.Vec) (bool, float64) { + ab := b.Sub(a) + ac := c.Sub(a) + ad := d.Sub(a) + + // Note that the `Norm` function of MATHEMATICA is equivalent to our `Length()` function. + nab := ab.Length() + ncd := d.Sub(c).Length() + nbd := d.Sub(b).Length() + nbc := c.Sub(b).Length() + nac := ac.Length() + nad := ad.Length() + + // Check for 0 edge lengths + if nab == 0 || ncd == 0 || + nbd == 0 || nbc == 0 || + nac == 0 || nad == 0 { + return true, 0 + } + + volume := 1.0 / 6.0 * math.Abs(ab.Cross(ac).Dot(ad)) + denom := (nab + ncd) * (nac + nbd) * (nad + nbc) + + // Tolerance derived from here: + // https://math.stackexchange.com/a/4709610/197913 + tolerance := 480.0 + + rho := tolerance * volume / denom + + return rho < 1, volume +} + +//----------------------------------------------------------------------------- + +// Reference: +// CCX source code: +// ccx_2.20/src/shape4tet.f +func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { + // Coordinates of the nodes. + var xl [3][4]float64 + + for i := 0; i < 4; i++ { + xl[0][i] = coords[i].X + xl[1][i] = coords[i].Y + xl[2][i] = coords[i].Z + } + + // Shape functions. + var shp [4][4]float64 + + shp[3][0] = 1.0 - xi - et - ze + shp[3][1] = xi + shp[3][2] = et + shp[3][3] = ze + + // local derivatives of the shape functions: xi-derivative + + shp[0][0] = -1.0 + shp[0][1] = 1.0 + shp[0][2] = 0.0 + shp[0][3] = 0.0 + + // local derivatives of the shape functions: eta-derivative + + shp[1][0] = -1.0 + shp[1][1] = 0.0 + shp[1][2] = 1.0 + shp[1][3] = 0.0 + + // local derivatives of the shape functions: zeta-derivative + + shp[2][0] = -1.0 + shp[2][1] = 0.0 + shp[2][2] = 0.0 + shp[2][3] = 1.0 + + // computation of the local derivative of the global coordinates (xs) + xs := [3][3]float64{} + for i := 0; i < 3; i++ { + for j := 0; j < 3; j++ { + xs[i][j] = 0.0 + for k := 0; k < 4; k++ { + xs[i][j] += xl[i][k] * shp[j][k] + } + } + } + + // computation of the jacobian determinant + xsj := xs[0][0]*(xs[1][1]*xs[2][2]-xs[1][2]*xs[2][1]) - + xs[0][1]*(xs[1][0]*xs[2][2]-xs[1][2]*xs[2][0]) + + xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) + + // According to CCX source code to detect nonpositive jacobian determinant in element + // + // Fortran threshold for non-positive Jacobian determinant is 1e-20. + // But, for example a bad element with non-positive Jacobian determinant + // of 0.0025717779019105687 is escaping the 1e-20 threshold. + // Seems like we need to make the threshold safer. + return xsj < 1e-20, xsj +} + +// Reference: +// CCX source code: +// ccx_2.20/src/shape10tet.f +func isBadGaussTet10(coords [10]v3.Vec, xi, et, ze float64) (bool, float64) { + // Coordinates of the nodes. + var xl [3][10]float64 + + for i := 0; i < 10; i++ { + xl[0][i] = coords[i].X + xl[1][i] = coords[i].Y + xl[2][i] = coords[i].Z + } + + // Shape functions. + var shp [4][10]float64 + + // Shape functions + a := 1.0 - xi - et - ze + shp[3][0] = (2.0*a - 1.0) * a + shp[3][1] = xi * (2.0*xi - 1.0) + shp[3][2] = et * (2.0*et - 1.0) + shp[3][3] = ze * (2.0*ze - 1.0) + shp[3][4] = 4.0 * xi * a + shp[3][5] = 4.0 * xi * et + shp[3][6] = 4.0 * et * a + shp[3][7] = 4.0 * ze * a + shp[3][8] = 4.0 * xi * ze + shp[3][9] = 4.0 * et * ze + + // Local derivatives of the shape functions: xi-derivative + shp[0][0] = 1.0 - 4.0*a + shp[0][1] = 4.0*xi - 1.0 + shp[0][2] = 0.0 + shp[0][3] = 0.0 + shp[0][4] = 4.0 * (a - xi) + shp[0][5] = 4.0 * et + shp[0][6] = -4.0 * et + shp[0][7] = -4.0 * ze + shp[0][8] = 4.0 * ze + shp[0][9] = 0.0 + + // Local derivatives of the shape functions: eta-derivative + shp[1][0] = 1.0 - 4.0*a + shp[1][1] = 0.0 + shp[1][2] = 4.0*et - 1.0 + shp[1][3] = 0.0 + shp[1][4] = -4.0 * xi + shp[1][5] = 4.0 * xi + shp[1][6] = 4.0 * (a - et) + shp[1][7] = -4.0 * ze + shp[1][8] = 0.0 + shp[1][9] = 4.0 * ze + + // Local derivatives of the shape functions: zeta-derivative + shp[2][0] = 1.0 - 4.0*a + shp[2][1] = 0.0 + shp[2][2] = 0.0 + shp[2][3] = 4.0*ze - 1.0 + shp[2][4] = -4.0 * xi + shp[2][5] = 0.0 + shp[2][6] = -4.0 * et + shp[2][7] = 4.0 * (a - ze) + shp[2][8] = 4.0 * xi + shp[2][9] = 4.0 * et + + // Computation of the local derivative of the global coordinates (xs) + var xs [3][3]float64 + for i := 0; i < 3; i++ { + for j := 0; j < 3; j++ { + xs[i][j] = 0.0 + for k := 0; k < 10; k++ { + xs[i][j] = xs[i][j] + xl[i][k]*shp[j][k] + } + } + } + + // computation of the jacobian determinant + xsj := xs[0][0]*(xs[1][1]*xs[2][2]-xs[1][2]*xs[2][1]) - + xs[0][1]*(xs[1][0]*xs[2][2]-xs[1][2]*xs[2][0]) + + xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) + + // According to CCX source code to detect nonpositive jacobian determinant in element + // + // Fortran threshold for non-positive Jacobian determinant is 1e-20. + // But, for example a bad element with non-positive Jacobian determinant + // of 0.0025717779019105687 is escaping the 1e-20 threshold. + // Seems like we need to make the threshold safer. + return xsj < 1e-20, xsj +} + +//----------------------------------------------------------------------------- + +func isBadTet4(coords [4]v3.Vec) (bool, float64) { + + // xi, et, and ze are the coordinates of the Gauss point + // in the integration scheme for the 4-node tetrahedral element. + // For this element type, there is typically only 1 Gauss point used, + // which is located at the centroid of the tetrahedron. + // The coordinates of this Gauss point are (xi, et, ze) = (1/4, 1/4, 1/4). + // Reference: + // ccx_2.20/src/gauss.f + var xi float64 = 0.25 + var et float64 = 0.25 + var ze float64 = 0.25 + + return isBadGaussTet4(coords, xi, et, ze) +} + +func isBadTet10(coords [10]v3.Vec) (bool, float64) { + // Gause points are according to CCX source code. + // Reference: + // ccx_2.20/src/gauss.f + var gaussPoints [4]v3.Vec + gaussPoints[0] = v3.Vec{0.138196601125011, 0.138196601125011, 0.138196601125011} + gaussPoints[1] = v3.Vec{0.585410196624968, 0.138196601125011, 0.138196601125011} + gaussPoints[2] = v3.Vec{0.138196601125011, 0.585410196624968, 0.138196601125011} + gaussPoints[3] = v3.Vec{0.138196601125011, 0.138196601125011, 0.585410196624968} + + var bad bool + var jacobianDeterminant float64 + + for i := 0; i < 4; i++ { + bad, jacobianDeterminant = isBadGaussTet10(coords, gaussPoints[i].X, gaussPoints[i].Y, gaussPoints[i].Z) + if bad { + return true, jacobianDeterminant + } + } + + return false, jacobianDeterminant +} + +//----------------------------------------------------------------------------- + +// If triangles are degenerate, then tetrahedra will be bad. +// To filter bad tetrahedra. +func degenerateTriangles(a, b, c, d v3.Vec) bool { + // 4 triangles are possible. + // Each triangle is a tetrahedron side. + t := Triangle3{} + t.V[0] = a + t.V[1] = b + t.V[2] = c + // Use the epsilon value of `vertexbuffer.go` + if t.Degenerate(0.0001) { + return true + } + t.V[0] = a + t.V[1] = b + t.V[2] = d + // Use the epsilon value of `vertexbuffer.go` + if t.Degenerate(0.0001) { + return true + } + t.V[0] = a + t.V[1] = c + t.V[2] = d + // Use the epsilon value of `vertexbuffer.go` + if t.Degenerate(0.0001) { + return true + } + t.V[0] = b + t.V[1] = c + t.V[2] = d + // Use the epsilon value of `vertexbuffer.go` + return t.Degenerate(0.0001) +} + +//----------------------------------------------------------------------------- + +// Specify the edges & corners used to create the tetrahedra. +// Keep the index from 0 to 11 for edges, +// but shift the index for corners. +// Corners were originally indexed from 0 to 7. +// So, corners would be indexed from 0+12 to 7+12 i.e. from 12 to 19. +// Manually created by: +// https://github.com/Megidd/tetrahedron-table +var mcTetrahedronTable = [256][]int{ + // 0b00000000 case 0: no cube corner has zero/negative value. + {}, + // 0b00000001 case 1: first cube corner has zero/negative value. + {12, 0, 3, 8}, + // 0b00000010 case 2 + {13, 1, 0, 9}, + // 0b00000011 case 3 + { + 12, 13, 3, 8, + 13, 1, 3, 8, + 13, 1, 8, 9, + }, + // 0b00000100 case 4 + {14, 2, 1, 10}, + // 0b00000101 case 5 + { + 12, 0, 3, 8, + 14, 2, 1, 10, + }, + // 0b00000110 case 6 + { + 13, 14, 0, 9, + 14, 2, 0, 9, + 14, 2, 9, 10, + }, + // 0b00000111 case 7 + { + 12, 13, 3, 8, + 13, 2, 3, 8, + 13, 14, 2, 8, + 14, 2, 8, 10, + 13, 14, 8, 10, + 13, 10, 8, 9, + }, + // 0b00001000 case 8 + { + 15, 3, 2, 11, + }, + // 0b00001001 case 9 + { + 12, 0, 2, 11, + 12, 2, 15, 11, + 12, 0, 11, 8, + }, + // 0b00001010 case 10 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + }, + // 0b00001011 case 11 + { + 15, 12, 2, 11, + 12, 1, 2, 11, + 12, 13, 1, 11, + 13, 1, 11, 9, + 12, 13, 11, 9, + 11, 12, 9, 8, + }, + // 0b00001100 case 12 + { + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00001101 case 13 + { + 12, 0, 1, 8, + 12, 1, 14, 8, + 1, 14, 8, 10, + 14, 15, 12, 8, + 14, 15, 8, 10, + 10, 15, 8, 11, + }, + // 0b00001110 case 14 + { + 0, 15, 3, 11, + 0, 14, 15, 11, + 0, 14, 11, 9, + 0, 13, 14, 9, + 14, 11, 9, 10, + }, + // 0b00001111 case 15 + { + 12, 13, 14, 10, + 12, 13, 10, 9, + 12, 9, 10, 8, + 12, 14, 15, 8, + 14, 15, 8, 10, + 15, 8, 10, 11, + }, + // 0b00010000 case 16 + {8, 4, 7, 16}, + // 0b00010001 case 17 + { + 12, 0, 3, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b00010010 case 18 + { + 8, 4, 7, 16, + 13, 1, 0, 9, + }, + // 0b00010011 case 19 + { + 3, 12, 1, 7, + 12, 13, 1, 7, + 12, 13, 7, 16, + 13, 1, 7, 9, + 13, 7, 16, 9, + 16, 9, 7, 4, + }, + // 0b00010100 case 20 + { + 8, 4, 7, 16, + 1, 14, 2, 10, + }, + // 0b00010101 case 21 + { + 1, 14, 2, 10, + 3, 12, 0, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b00010110 case 22 + { + 8, 4, 7, 16, + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 10, + }, + // 0b00010111 case 23 + { + 3, 12, 2, 7, + 12, 13, 2, 7, + 13, 2, 7, 4, + 13, 2, 4, 9, + 12, 13, 7, 16, + 16, 13, 7, 4, + 13, 14, 2, 9, + 14, 2, 9, 10, + }, + // 0b00011000 case 24 + { + 8, 4, 7, 16, + 2, 15, 3, 11, + }, + // 0b00011001 case 25 + { + 12, 0, 2, 4, + 12, 2, 15, 4, + 2, 15, 4, 11, + 12, 4, 15, 11, + 12, 4, 11, 7, + 12, 4, 7, 16, + }, + // 0b00011010 case 26 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + 8, 4, 7, 16, + }, + // 0b00011011 case 27 + { + 12, 2, 15, 11, + 12, 1, 2, 11, + 12, 13, 1, 11, + 13, 1, 11, 9, + 12, 13, 11, 9, + 12, 9, 11, 4, + 12, 4, 11, 16, + 11, 16, 4, 7, + }, + // 0b00011100 case 28 + { + 8, 4, 7, 16, + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00011101 case 29 + { + 1, 14, 15, 10, + 15, 1, 10, 11, + 12, 1, 15, 11, + 12, 0, 1, 4, + 12, 1, 11, 4, + 12, 4, 11, 7, + 12, 4, 7, 16, + }, + // 0b00011110 case 30 + { + 8, 4, 7, 16, + 13, 14, 0, 9, + 14, 3, 0, 9, + 14, 15, 3, 9, + 15, 3, 9, 11, + 14, 15, 9, 11, + 14, 11, 9, 10, + }, + // 0b00011111 case 31 + { + 13, 14, 15, 11, + 13, 14, 11, 9, + 14, 11, 9, 10, + 12, 13, 15, 9, + 12, 9, 15, 11, + 12, 9, 11, 7, + 12, 9, 7, 16, + 16, 9, 7, 4, + }, + // 0b00100000 case 32 + {9, 5, 4, 17}, + // 0b00100001 case 33 + { + 12, 0, 3, 8, + 9, 5, 4, 17, + }, + // 0b00100010 case 34 + { + 0, 13, 1, 5, + 0, 13, 5, 4, + 4, 13, 5, 17, + }, + // 0b00100011 case 35 + { + 13, 1, 3, 5, + 13, 3, 12, 5, + 12, 5, 3, 4, + 12, 4, 3, 8, + 12, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00100100 case 36 + { + 1, 14, 2, 10, + 9, 5, 4, 17, + }, + // 0b00100101 case 37 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 4, 9, 5, 17, + }, + // 0b00100110 case 38 + { + 0, 14, 2, 4, + 14, 2, 4, 5, + 14, 2, 5, 10, + 0, 13, 14, 4, + 13, 14, 4, 5, + 13, 5, 4, 17, + }, + // 0b00100111 case 39 + { + 13, 14, 2, 10, + 12, 13, 2, 10, + 12, 2, 3, 10, + 12, 10, 3, 8, + 12, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 4, + 13, 5, 4, 17, + }, + // 0b00101000 case 40 + { + 9, 5, 4, 17, + 2, 15, 3, 11, + }, + // 0b00101001 case 41 + { + 9, 5, 4, 17, + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + }, + // 0b00101010 case 42 + { + 2, 15, 3, 11, + 0, 13, 1, 4, + 4, 13, 1, 5, + 4, 13, 5, 17, + }, + // 0b00101011 case 43 + { + 2, 15, 12, 11, + 11, 12, 2, 8, + 12, 1, 2, 8, + 12, 13, 1, 8, + 8, 1, 2, 5, + 13, 1, 8, 5, + 8, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00101100 case 44 + { + 9, 5, 4, 17, + 1, 14, 3, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00101101 case 45 + { + 9, 5, 4, 17, + 1, 14, 0, 10, + 14, 12, 0, 10, + 12, 0, 10, 8, + 14, 15, 12, 10, + 15, 12, 10, 8, + 15, 8, 10, 11, + }, + // 0b00101110 case 46 + { + 14, 15, 3, 11, + 14, 3, 0, 11, + 0, 14, 11, 5, + 14, 11, 5, 10, + 0, 13, 14, 5, + 0, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b00101111 case 47 + { + 14, 15, 12, 8, + 14, 15, 8, 10, + 15, 8, 10, 11, + 12, 13, 14, 10, + 12, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 4, + 13, 5, 4, 17, + }, + // 0b00110000 case 48 + { + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + }, + // 0b00110001 case 49 + { + 3, 12, 0, 5, + 3, 12, 5, 7, + 12, 0, 7, 16, + 0, 5, 7, 16, + 0, 5, 16, 9, + 9, 5, 16, 17, + }, + // 0b00110010 case 50 + { + 0, 13, 1, 7, + 13, 1, 7, 5, + 0, 13, 5, 17, + 0, 5, 7, 17, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b00110011 case 51 + { + 12, 1, 3, 5, + 3, 12, 5, 7, + 12, 13, 1, 5, + 12, 13, 5, 17, + 12, 17, 5, 7, + 12, 17, 7, 16, + }, + // 0b00110100 case 52 + { + 1, 14, 2, 10, + 7, 8, 5, 16, + 8, 9, 5, 16, + 16, 9, 5, 17, + }, + // 0b00110101 case 53 + { + 1, 14, 2, 10, + 3, 12, 0, 5, + 3, 12, 5, 7, + 0, 9, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 12, + 12, 17, 7, 16, + }, + // 0b00110110 case 54 + { + 13, 14, 2, 10, + 0, 13, 2, 10, + 0, 10, 2, 8, + 0, 13, 10, 8, + 13, 10, 8, 5, + 13, 5, 8, 17, + 8, 17, 5, 7, + 8, 17, 7, 16, + }, + // 0b00110111 case 55 + { + 13, 14, 2, 10, + 13, 2, 3, 10, + 13, 10, 3, 5, + 12, 13, 3, 5, + 12, 13, 5, 17, + 3, 12, 5, 7, + 12, 17, 5, 7, + 12, 17, 7, 16, + }, + // 0b00111000 case 56 + { + 15, 3, 2, 11, + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + }, + // 0b00111001 case 57 + { + 12, 0, 2, 9, + 15, 12, 2, 9, + 2, 15, 9, 11, + 15, 12, 9, 11, + 12, 9, 11, 7, + 12, 9, 7, 16, + 9, 7, 16, 5, + 9, 5, 16, 17, + }, + // 0b00111010 case 58 + { + 15, 3, 2, 11, + 0, 13, 1, 8, + 13, 1, 8, 7, + 13, 1, 7, 5, + 13, 7, 8, 16, + 13, 7, 16, 5, + 13, 5, 16, 17, + }, + // 0b00111011 case 59 + { + 12, 13, 1, 17, + 12, 17, 1, 5, + 12, 5, 1, 7, + 12, 17, 5, 7, + 12, 17, 7, 16, + 2, 12, 1, 7, + 15, 12, 2, 7, + 15, 7, 2, 11, + }, + // 0b00111100 case 60 + { + 8, 5, 7, 16, + 8, 9, 5, 16, + 9, 5, 16, 17, + 14, 3, 1, 10, + 14, 15, 3, 10, + 15, 3, 10, 11, + }, + // 0b00111101 case 61 + { + 0, 9, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 16, + 0, 16, 7, 12, + 12, 0, 11, 7, + 14, 0, 1, 10, + 12, 0, 15, 11, + 14, 15, 0, 11, + 14, 11, 0, 10, + }, + // 0b00111110 case 62 + { + 15, 3, 0, 11, + 14, 15, 0, 11, + 14, 11, 0, 10, + 14, 0, 13, 10, + 0, 13, 10, 5, + 0, 13, 5, 17, + 0, 17, 5, 7, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b00111111 case 63 + { + 12, 14, 15, 11, + 12, 14, 11, 10, + 12, 13, 14, 10, + 11, 12, 10, 7, + 12, 13, 10, 7, + 12, 13, 7, 16, + 13, 10, 7, 5, + 13, 5, 7, 17, + 13, 7, 16, 17, + }, + // 0b01000000 case 64 + {10, 6, 5, 18}, + // 0b01000001 case 65 + { + 12, 0, 3, 8, + 10, 6, 5, 18, + }, + // 0b01000010 case 66 + { + 0, 13, 1, 9, + 10, 6, 5, 18, + }, + // 0b01000011 case 67 + { + 10, 6, 5, 18, + 3, 12, 1, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + }, + // 0b01000100 case 68 + { + 1, 14, 2, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01000101 case 69 + { + 12, 0, 3, 8, + 14, 2, 1, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01000110 case 70 + { + 0, 13, 2, 6, + 0, 13, 6, 9, + 13, 14, 2, 6, + 13, 14, 6, 9, + 9, 14, 6, 5, + 14, 6, 5, 18, + }, + // 0b01000111 case 71 + { + 3, 12, 2, 8, + 12, 13, 2, 8, + 13, 2, 8, 9, + 13, 14, 2, 9, + 9, 2, 8, 5, + 9, 14, 2, 5, + 14, 2, 5, 6, + 14, 6, 5, 18, + }, + // 0b01001000 case 72 + { + 10, 6, 5, 18, + 15, 3, 2, 11, + }, + // 0b01001001 case 73 + { + 10, 6, 5, 18, + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + }, + // 0b01001010 case 74 + { + 0, 13, 1, 9, + 2, 15, 3, 11, + 10, 6, 5, 18, + }, + // 0b01001011 case 75 + { + 10, 6, 5, 18, + 2, 15, 1, 11, + 15, 13, 1, 11, + 13, 1, 11, 9, + 15, 12, 13, 11, + 11, 12, 13, 9, + 11, 12, 9, 8, + }, + // 0b01001100 case 76 + { + 14, 15, 3, 11, + 1, 14, 3, 11, + 1, 11, 3, 5, + 1, 14, 11, 5, + 5, 14, 11, 6, + 5, 14, 6, 18, + }, + // 0b01001101 case 77 + { + 12, 0, 15, 8, + 15, 8, 0, 11, + 14, 0, 1, 5, + 14, 15, 0, 11, + 14, 0, 5, 6, + 14, 11, 0, 6, + 14, 6, 5, 18, + }, + // 0b01001110 case 78 + { + 0, 13, 14, 9, + 14, 15, 3, 11, + 14, 3, 0, 9, + 14, 11, 3, 6, + 14, 3, 9, 5, + 14, 6, 3, 5, + 14, 6, 5, 18, + }, + // 0b01001111 case 79 + { + 15, 12, 13, 8, + 13, 15, 8, 11, + 13, 11, 8, 9, + 13, 14, 15, 9, + 14, 15, 9, 11, + 9, 14, 11, 5, + 14, 11, 5, 6, + 14, 6, 5, 18, + }, + // 0b01010000 case 80 + { + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01010001 case 81 + { + 10, 6, 5, 18, + 12, 0, 3, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + }, + // 0b01010010 case 82 + { + 13, 1, 0, 9, + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01010011 case 83 + { + 10, 6, 5, 18, + 12, 13, 1, 9, + 3, 12, 1, 9, + 3, 9, 1, 7, + 3, 12, 9, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + }, + // 0b01010100 case 84 + { + 8, 4, 7, 16, + 14, 2, 1, 6, + 1, 14, 6, 5, + 5, 14, 6, 18, + }, + // 0b01010101 case 85 + { + 3, 12, 0, 7, + 12, 0, 7, 4, + 12, 4, 7, 16, + 1, 14, 2, 5, + 14, 2, 5, 6, + 5, 14, 6, 18, + }, + // 0b01010110 case 86 + { + 8, 4, 7, 16, + 0, 13, 2, 6, + 0, 13, 6, 9, + 13, 14, 2, 6, + 13, 14, 6, 9, + 14, 6, 9, 5, + 14, 6, 5, 18, + }, + // 0b01010111 case 87 + { + 13, 2, 3, 9, + 13, 3, 12, 9, + 13, 14, 2, 9, + 14, 2, 9, 6, + 3, 12, 9, 7, + 12, 9, 7, 4, + 14, 6, 9, 5, + 12, 4, 7, 16, + 14, 6, 5, 18, + }, + // 0b01011000 case 88 + { + 8, 4, 7, 16, + 10, 6, 5, 18, + 15, 3, 2, 11, + }, + // 0b01011001 case 89 + { + 10, 6, 5, 18, + 2, 15, 0, 4, + 2, 15, 4, 11, + 15, 12, 0, 4, + 15, 12, 4, 11, + 11, 12, 4, 7, + 7, 12, 4, 16, + }, + // 0b01011010 case 90 + { + 13, 1, 0, 9, + 2, 15, 3, 11, + 8, 4, 7, 16, + 10, 6, 5, 18, + }, + // 0b01011011 case 91 + { + 10, 6, 5, 18, + 15, 1, 2, 11, + 15, 13, 1, 11, + 13, 1, 11, 9, + 15, 12, 13, 11, + 12, 13, 11, 9, + 12, 9, 11, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + }, + // 0b01011100 case 92 + { + 8, 4, 7, 16, + 1, 15, 3, 5, + 15, 3, 5, 6, + 15, 3, 6, 11, + 1, 14, 15, 6, + 1, 14, 6, 5, + 14, 6, 5, 18, + }, + // 0b01011101 case 93 + { + 15, 0, 1, 11, + 15, 12, 0, 11, + 1, 14, 15, 11, + 11, 12, 0, 4, + 11, 1, 14, 5, + 11, 12, 4, 7, + 11, 5, 14, 6, + 14, 6, 5, 18, + 12, 4, 7, 16, + }, + // 0b01011110 case 94 + { + 8, 4, 7, 16, + 13, 3, 0, 9, + 13, 15, 3, 9, + 15, 3, 9, 11, + 13, 14, 15, 9, + 14, 15, 9, 11, + 14, 11, 9, 5, + 14, 11, 5, 6, + 14, 6, 5, 18, + }, + // 0b01011111 case 95 + { + 15, 12, 13, 11, + 11, 12, 13, 9, + 11, 12, 9, 7, + 12, 9, 7, 4, + 12, 4, 7, 16, + 13, 14, 15, 9, + 14, 15, 9, 11, + 9, 14, 11, 5, + 5, 14, 11, 6, + 14, 6, 5, 18, + }, + // 0b01100000 case 96 + { + 9, 10, 4, 17, + 10, 6, 4, 17, + 10, 6, 17, 18, + }, + // 0b01100001 case 97 + { + 12, 0, 3, 8, + 4, 9, 6, 17, + 9, 10, 6, 17, + 17, 10, 6, 18, + }, + // 0b01100010 case 98 + { + 0, 13, 1, 6, + 1, 10, 6, 18, + 13, 1, 6, 18, + 0, 13, 6, 4, + 13, 18, 6, 4, + 13, 18, 4, 17, + }, + // 0b01100011 case 99 + { + 3, 12, 1, 8, + 12, 13, 1, 8, + 8, 13, 1, 17, + 1, 8, 17, 4, + 1, 6, 8, 4, + 1, 4, 17, 6, + 1, 6, 17, 10, + 17, 10, 6, 18, + }, + // 0b01100100 case 100 + { + 1, 14, 2, 6, + 1, 2, 4, 6, + 1, 14, 6, 18, + 1, 18, 6, 4, + 1, 18, 4, 9, + 9, 18, 4, 17, + }, + // 0b01100101 case 101 + { + 3, 12, 0, 8, + 1, 14, 2, 9, + 9, 14, 2, 4, + 14, 2, 4, 6, + 9, 14, 4, 17, + 14, 6, 4, 17, + 14, 6, 17, 18, + }, + // 0b01100110 case 102 + { + 0, 13, 2, 4, + 13, 14, 2, 4, + 14, 2, 4, 6, + 14, 18, 6, 4, + 14, 18, 4, 13, + 13, 18, 4, 17, + }, + // 0b01100111 case 103 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 13, 14, 2, 8, + 14, 2, 8, 4, + 13, 14, 8, 4, + 14, 2, 4, 6, + 13, 14, 4, 17, + 14, 4, 17, 6, + 14, 6, 17, 18, + }, + // 0b01101000 case 104 + { + 2, 15, 3, 11, + 4, 9, 6, 17, + 9, 10, 6, 17, + 10, 6, 17, 18, + }, + // 0b01101001 case 105 + { + 2, 15, 0, 11, + 15, 12, 0, 11, + 12, 0, 11, 8, + 4, 9, 6, 17, + 9, 10, 6, 17, + 10, 6, 17, 18, + }, + // 0b01101010 case 106 + { + 2, 15, 3, 11, + 0, 13, 1, 6, + 0, 13, 6, 4, + 1, 10, 6, 4, + 13, 1, 4, 17, + 10, 6, 4, 18, + 17, 1, 4, 10, + 17, 10, 4, 18, + }, + // 0b01101011 case 107 + { + 15, 1, 2, 11, + 15, 12, 1, 11, + 12, 1, 11, 8, + 12, 13, 1, 8, + 8, 13, 1, 4, + 13, 1, 4, 17, + 1, 6, 4, 17, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01101100 case 108 + { + 1, 14, 3, 9, + 14, 15, 3, 9, + 15, 3, 9, 11, + 14, 15, 9, 11, + 14, 11, 9, 6, + 14, 6, 9, 18, + 9, 18, 6, 4, + 4, 9, 18, 17, + }, + // 0b01101101 case 109 + { + 12, 0, 1, 8, + 15, 12, 1, 8, + 15, 8, 1, 11, + 14, 15, 1, 11, + 1, 14, 11, 6, + 1, 14, 6, 18, + 1, 18, 6, 4, + 1, 18, 4, 17, + 1, 17, 4, 9, + }, + // 0b01101110 case 110 + { + 14, 15, 3, 11, + 0, 14, 3, 11, + 0, 13, 14, 11, + 0, 13, 11, 6, + 13, 14, 11, 6, + 13, 14, 6, 18, + 0, 13, 6, 4, + 13, 18, 6, 4, + 13, 18, 4, 17, + }, + // 0b01101111 case 111 + { + 15, 12, 13, 11, + 13, 14, 15, 11, + 12, 13, 11, 8, + 8, 13, 14, 4, + 14, 8, 4, 11, + 14, 11, 4, 6, + 13, 14, 4, 17, + 14, 4, 17, 6, + 14, 6, 17, 18, + }, + // 0b01110000 case 112 + { + 8, 9, 10, 7, + 9, 10, 7, 6, + 8, 9, 7, 16, + 9, 10, 6, 18, + 9, 7, 16, 17, + 9, 6, 7, 17, + 9, 18, 6, 17, + }, + // 0b01110001 case 113 + { + 12, 0, 3, 7, + 12, 0, 7, 16, + 0, 9, 10, 7, + 0, 9, 7, 16, + 9, 10, 16, 17, + 10, 7, 16, 17, + 10, 7, 17, 6, + 10, 6, 17, 18, + }, + // 0b01110010 case 114 + { + 0, 13, 1, 10, + 0, 13, 10, 8, + 13, 10, 8, 6, + 13, 6, 8, 7, + 13, 10, 6, 18, + 13, 7, 8, 16, + 13, 6, 7, 17, + 13, 18, 6, 17, + 13, 7, 16, 17, + }, + // 0b01110011 case 115 + { + 3, 12, 13, 7, + 12, 13, 7, 16, + 13, 1, 3, 7, + 13, 1, 16, 17, + 1, 7, 16, 6, + 1, 6, 16, 17, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01110100 case 116 + { + 1, 14, 2, 6, + 1, 14, 6, 18, + 1, 18, 6, 7, + 1, 8, 9, 16, + 1, 7, 8, 16, + 1, 18, 7, 16, + 1, 18, 16, 9, + 9, 18, 16, 17, + }, + // 0b01110101 case 117 + { + 3, 12, 0, 9, + 3, 12, 9, 7, + 12, 9, 7, 16, + 9, 7, 16, 17, + 9, 6, 7, 17, + 1, 14, 2, 9, + 14, 2, 9, 6, + 14, 6, 9, 17, + 14, 6, 17, 18, + }, + // 0b01110110 case 118 + { + 13, 14, 2, 6, + 0, 13, 2, 6, + 13, 14, 6, 18, + 0, 13, 18, 17, + 0, 17, 18, 6, + 0, 17, 6, 7, + 0, 17, 7, 16, + 0, 7, 8, 16, + }, + // 0b01110111 case 119 + { + 12, 2, 3, 7, + 12, 14, 2, 7, + 14, 2, 7, 6, + 12, 13, 14, 7, + 12, 13, 7, 16, + 14, 6, 7, 18, + 14, 18, 7, 16, + 13, 14, 16, 18, + 13, 18, 16, 17, + }, + // 0b01111000 case 120 + { + 2, 15, 3, 11, + 8, 9, 10, 7, + 9, 10, 7, 6, + 9, 10, 6, 18, + 8, 9, 7, 16, + 9, 18, 6, 17, + 9, 6, 7, 17, + 9, 7, 16, 17, + }, + // 0b01111001 case 121 + { + 15, 0, 2, 7, + 15, 7, 2, 11, + 15, 12, 0, 7, + 12, 0, 7, 16, + 16, 0, 7, 9, + 16, 9, 7, 17, + 9, 10, 7, 17, + 10, 7, 17, 18, + 10, 7, 18, 6, + }, + // 0b01111010 case 122 + { + 15, 3, 2, 11, + 0, 13, 1, 10, + 0, 13, 10, 8, + 13, 10, 8, 6, + 8, 13, 6, 7, + 13, 6, 7, 17, + 13, 10, 6, 17, + 13, 7, 8, 17, + 17, 10, 6, 18, + 17, 7, 8, 16, + }, + // 0b01111011 case 123 + { + 15, 1, 2, 11, + 15, 12, 1, 11, + 12, 13, 1, 11, + 13, 1, 11, 7, + 12, 13, 11, 7, + 12, 13, 7, 16, + 13, 7, 16, 17, + 13, 1, 7, 17, + 1, 7, 17, 6, + 1, 6, 17, 10, + 10, 6, 17, 18, + }, + // 0b01111100 case 124 + { + 3, 11, 6, 15, + 1, 15, 3, 6, + 1, 14, 15, 6, + 1, 14, 6, 18, + 1, 18, 6, 9, + 9, 18, 6, 17, + 8, 9, 6, 17, + 8, 17, 6, 7, + 8, 17, 7, 16, + }, + // 0b01111101 case 125 + { + 12, 0, 1, 9, + 12, 1, 14, 9, + 12, 14, 15, 9, + 12, 9, 15, 17, + 14, 15, 9, 17, + 15, 12, 17, 16, + 15, 17, 14, 18, + 15, 16, 17, 7, + 15, 17, 18, 6, + 15, 7, 17, 11, + 15, 17, 6, 11, + 11, 6, 7, 17, + }, + // 0b01111110 case 126 + { + 15, 3, 0, 11, + 14, 15, 0, 11, + 0, 14, 11, 6, + 0, 13, 14, 6, + 13, 14, 6, 18, + 0, 13, 18, 17, + 0, 18, 6, 17, + 0, 17, 6, 7, + 0, 17, 7, 8, + 8, 17, 7, 16, + }, + // 0b01111111 case 127 + { + 6, 7, 11, 15, + 12, 13, 15, 7, + 13, 14, 15, 7, + 14, 15, 7, 6, + 13, 14, 7, 6, + 13, 14, 6, 18, + 12, 13, 7, 16, + 13, 18, 6, 17, + 13, 6, 7, 17, + 13, 7, 16, 17, + }, + // 0b10000000 case 128 + { + 11, 7, 6, 19, + }, + // 0b10000001 case 129 + { + 3, 12, 0, 8, + 11, 7, 6, 19, + }, + // 0b10000010 case 130 + { + 0, 13, 1, 9, + 11, 7, 6, 19, + }, + // 0b10000011 case 131 + { + 11, 7, 6, 19, + 3, 12, 1, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + }, + // 0b10000100 case 132 + { + 1, 14, 2, 10, + 11, 7, 6, 19, + }, + // 0b10000101 case 133 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 11, 7, 6, 19, + }, + // 0b10000110 case 134 + { + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 10, + 11, 7, 6, 19, + }, + // 0b10000111 case 135 + { + 12, 2, 3, 8, + 12, 14, 2, 8, + 14, 2, 8, 10, + 12, 13, 14, 8, + 13, 14, 8, 10, + 13, 10, 8, 9, + 11, 7, 6, 19, + }, + // 0b10001000 case 136 + { + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001001 case 137 + { + 2, 15, 0, 6, + 15, 12, 0, 6, + 12, 0, 6, 7, + 12, 0, 7, 8, + 15, 12, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001010 case 138 + { + 0, 13, 1, 9, + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10001011 case 139 + { + 12, 13, 1, 9, + 12, 9, 1, 8, + 12, 1, 2, 8, + 2, 8, 1, 7, + 2, 7, 1, 6, + 2, 15, 12, 8, + 2, 15, 8, 7, + 2, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10001100 case 140 + { + 15, 3, 1, 7, + 14, 15, 1, 7, + 1, 14, 7, 6, + 1, 14, 6, 10, + 14, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10001101 case 141 + { + 14, 0, 1, 10, + 14, 12, 0, 10, + 12, 0, 10, 8, + 14, 15, 12, 10, + 15, 12, 10, 8, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + }, + // 0b10001110 case 142 + { + 0, 13, 14, 9, + 14, 0, 9, 10, + 14, 15, 0, 10, + 15, 3, 0, 10, + 10, 3, 0, 7, + 10, 15, 3, 7, + 10, 15, 7, 6, + 6, 15, 7, 19, + }, + // 0b10001111 case 143 + { + 14, 15, 12, 8, + 14, 15, 8, 10, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + 12, 13, 14, 10, + 12, 13, 10, 8, + 8, 13, 10, 9, + }, + // 0b10010000 case 144 + { + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010001 case 145 + { + 3, 12, 0, 4, + 3, 4, 0, 6, + 12, 4, 6, 16, + 3, 12, 6, 16, + 3, 16, 6, 19, + 3, 19, 6, 11, + }, + // 0b10010010 case 146 + { + 0, 13, 1, 9, + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010011 case 147 + { + 3, 13, 1, 9, + 3, 12, 13, 9, + 3, 12, 9, 6, + 12, 9, 6, 4, + 3, 12, 4, 16, + 3, 16, 4, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10010100 case 148 + { + 1, 14, 2, 10, + 11, 8, 6, 19, + 8, 4, 6, 19, + 8, 4, 19, 16, + }, + // 0b10010101 case 149 + { + 1, 14, 2, 10, + 3, 12, 0, 11, + 12, 0, 11, 6, + 12, 6, 11, 19, + 0, 6, 19, 4, + 12, 0, 19, 4, + 12, 4, 19, 16, + }, + // 0b10010110 case 150 + { + 13, 14, 0, 9, + 14, 2, 0, 9, + 14, 2, 9, 10, + 11, 8, 6, 19, + 8, 6, 19, 4, + 8, 4, 19, 16, + }, + // 0b10010111 case 151 + { + 3, 14, 2, 10, + 3, 13, 14, 10, + 3, 13, 10, 9, + 3, 12, 13, 9, + 3, 12, 9, 4, + 3, 12, 4, 16, + 3, 16, 4, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10011000 case 152 + { + 2, 15, 3, 8, + 2, 15, 8, 4, + 15, 8, 4, 16, + 2, 15, 4, 6, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011001 case 153 + { + 12, 0, 2, 4, + 15, 12, 2, 4, + 2, 15, 4, 6, + 12, 4, 15, 16, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011010 case 154 + { + 0, 13, 1, 9, + 2, 15, 3, 8, + 2, 15, 8, 4, + 15, 8, 4, 16, + 2, 15, 4, 6, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011011 case 155 + { + 2, 13, 1, 9, + 2, 13, 9, 4, + 12, 13, 2, 4, + 15, 12, 2, 4, + 2, 15, 4, 6, + 15, 12, 4, 16, + 15, 16, 4, 6, + 15, 16, 6, 19, + }, + // 0b10011100 case 156 + { + 14, 3, 1, 8, + 14, 8, 1, 10, + 14, 15, 3, 8, + 14, 15, 8, 10, + 10, 15, 8, 6, + 15, 8, 6, 19, + 6, 19, 8, 4, + 19, 8, 4, 16, + }, + // 0b10011101 case 157 + { + 14, 0, 1, 10, + 14, 15, 0, 10, + 15, 12, 0, 10, + 12, 0, 10, 6, + 15, 12, 10, 6, + 12, 0, 6, 4, + 15, 12, 6, 19, + 12, 4, 6, 19, + 12, 4, 19, 16, + }, + // 0b10011110 case 158 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 10, + 14, 15, 3, 10, + 15, 3, 10, 6, + 15, 3, 6, 19, + 3, 6, 19, 4, + 3, 4, 19, 8, + 8, 4, 19, 16, + }, + // 0b10011111 case 159 + { + 12, 13, 14, 10, + 12, 13, 10, 9, + 12, 14, 15, 10, + 15, 9, 10, 6, + 15, 12, 9, 6, + 12, 9, 6, 4, + 15, 12, 6, 19, + 12, 6, 19, 4, + 12, 4, 19, 16, + }, + // 0b10100000 case 160 + { + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100001 case 161 + { + 3, 12, 0, 8, + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100010 case 162 + { + 0, 13, 1, 4, + 13, 1, 4, 5, + 4, 13, 5, 17, + 11, 7, 6, 19, + }, + // 0b10100011 case 163 + { + 3, 13, 1, 5, + 3, 12, 13, 5, + 12, 13, 5, 17, + 3, 17, 5, 4, + 3, 12, 17, 4, + 3, 12, 4, 8, + 11, 7, 6, 19, + }, + // 0b10100100 case 164 + { + 1, 14, 2, 10, + 11, 7, 6, 19, + 9, 5, 4, 17, + }, + // 0b10100101 case 165 + { + 3, 12, 0, 8, + 1, 14, 2, 10, + 9, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100110 case 166 + { + 14, 2, 0, 10, + 13, 14, 0, 10, + 0, 13, 10, 5, + 0, 13, 5, 4, + 13, 5, 4, 17, + 11, 7, 6, 19, + }, + // 0b10100111 case 167 + { + 11, 7, 6, 19, + 3, 14, 2, 10, + 3, 12, 14, 10, + 3, 12, 10, 8, + 12, 13, 14, 10, + 12, 13, 10, 8, + 8, 13, 10, 5, + 8, 13, 5, 4, + 13, 5, 4, 17, + }, + // 0b10101000 case 168 + { + 9, 5, 4, 17, + 2, 15, 3, 6, + 15, 3, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101001 case 169 + { + 9, 5, 4, 17, + 2, 12, 0, 6, + 12, 0, 6, 7, + 12, 0, 7, 8, + 2, 15, 12, 6, + 15, 12, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101010 case 170 + { + 0, 13, 1, 4, + 13, 1, 4, 5, + 13, 5, 4, 17, + 2, 15, 3, 6, + 15, 3, 6, 7, + 15, 7, 6, 19, + }, + // 0b10101011 case 171 + { + 2, 12, 1, 8, + 12, 13, 1, 8, + 2, 15, 12, 8, + 8, 13, 1, 5, + 8, 13, 5, 4, + 4, 13, 5, 17, + 2, 15, 8, 6, + 15, 8, 6, 7, + 6, 15, 7, 19, + }, + // 0b10101100 case 172 + { + 9, 5, 4, 17, + 1, 15, 3, 7, + 1, 14, 15, 7, + 1, 14, 7, 6, + 1, 14, 6, 10, + 14, 15, 7, 6, + 15, 7, 6, 19, + }, + // 0b10101101 case 173 + { + 9, 5, 4, 17, + 1, 12, 0, 8, + 14, 12, 1, 8, + 14, 15, 12, 8, + 14, 8, 1, 10, + 14, 15, 8, 10, + 10, 15, 8, 6, + 6, 15, 8, 7, + 6, 15, 7, 19, + }, + // 0b10101110 case 174 + { + 13, 14, 0, 10, + 14, 3, 0, 10, + 14, 15, 3, 10, + 0, 13, 10, 5, + 0, 5, 10, 4, + 0, 13, 5, 4, + 13, 5, 4, 17, + 15, 3, 10, 7, + 15, 7, 10, 6, + 15, 7, 6, 19, + }, + // 0b10101111 case 175 + { + 12, 13, 14, 10, + 12, 14, 15, 10, + 12, 13, 10, 8, + 10, 15, 12, 8, + 10, 15, 8, 6, + 15, 8, 6, 7, + 15, 7, 6, 19, + 13, 10, 8, 4, + 13, 10, 4, 5, + 13, 5, 4, 17, + }, + // 0b10110000 case 176 + { + 11, 8, 9, 5, + 11, 8, 5, 6, + 8, 9, 5, 17, + 8, 6, 11, 19, + 8, 17, 5, 16, + 8, 5, 6, 16, + 8, 6, 19, 16, + }, + // 0b10110001 case 177 + { + 12, 0, 3, 11, + 11, 12, 0, 9, + 11, 12, 9, 6, + 12, 9, 6, 5, + 12, 6, 11, 19, + 12, 9, 5, 17, + 12, 17, 5, 16, + 12, 5, 6, 16, + 12, 6, 19, 16, + }, + // 0b10110010 case 178 + { + 0, 13, 1, 5, + 0, 13, 5, 17, + 0, 17, 5, 6, + 0, 17, 6, 11, + 11, 17, 6, 19, + 0, 17, 11, 19, + 0, 19, 11, 8, + 0, 17, 19, 8, + 8, 17, 19, 16, + }, + // 0b10110011 case 179 + { + 3, 13, 1, 5, + 3, 12, 13, 5, + 12, 13, 5, 17, + 3, 12, 17, 16, + 3, 17, 5, 16, + 3, 16, 5, 6, + 3, 16, 6, 11, + 16, 6, 11, 19, + }, + // 0b10110100 case 180 + { + 11, 8, 9, 5, + 11, 8, 5, 6, + 8, 9, 5, 17, + 8, 17, 5, 16, + 8, 5, 6, 16, + 8, 6, 11, 19, + 8, 6, 19, 16, + 1, 14, 2, 10, + }, + // 0b10110101 case 181 + { + 1, 14, 2, 10, + 3, 12, 0, 9, + 3, 12, 9, 11, + 11, 12, 9, 5, + 11, 12, 5, 6, + 12, 9, 5, 17, + 11, 12, 6, 19, + 12, 17, 5, 16, + 12, 5, 6, 16, + 12, 6, 19, 16, + }, + // 0b10110110 case 182 + { + 13, 14, 2, 10, + 0, 13, 2, 10, + 0, 10, 2, 5, + 0, 13, 10, 5, + 0, 13, 5, 17, + 0, 17, 5, 8, + 8, 17, 5, 16, + 11, 8, 5, 16, + 11, 16, 5, 6, + 11, 16, 6, 19, + }, + // 0b10110111 case 183 + { + 3, 14, 2, 10, + 3, 13, 14, 10, + 3, 12, 13, 10, + 3, 12, 10, 5, + 12, 13, 10, 5, + 12, 13, 5, 17, + 3, 12, 17, 16, + 3, 17, 5, 16, + 3, 16, 5, 6, + 3, 16, 6, 11, + 11, 16, 6, 19, + }, + // 0b10111000 case 184 + { + 8, 9, 5, 17, + 8, 17, 5, 16, + 2, 15, 3, 8, + 2, 15, 8, 5, + 2, 15, 5, 6, + 15, 8, 5, 6, + 6, 8, 5, 16, + 6, 15, 8, 19, + 6, 19, 8, 16, + }, + // 0b10111001 case 185 + { + 2, 15, 0, 6, + 15, 12, 0, 6, + 15, 12, 6, 19, + 12, 0, 19, 16, + 0, 6, 19, 16, + 0, 6, 16, 5, + 0, 5, 16, 9, + 16, 9, 5, 17, + }, + // 0b10111010 case 186 + { + 0, 13, 1, 8, + 13, 1, 8, 5, + 8, 13, 5, 17, + 8, 17, 5, 16, + 8, 16, 5, 6, + 2, 15, 3, 8, + 2, 15, 8, 6, + 15, 8, 6, 16, + 15, 16, 6, 19, + }, + // 0b10111011 case 187 + { + 2, 13, 1, 5, + 2, 12, 13, 5, + 12, 13, 5, 17, + 12, 17, 5, 16, + 12, 2, 15, 5, + 2, 15, 5, 6, + 15, 12, 5, 16, + 15, 16, 5, 6, + 15, 16, 6, 19, + }, + // 0b10111100 case 188 + { + 14, 3, 1, 6, + 1, 14, 6, 10, + 14, 15, 3, 6, + 15, 3, 6, 19, + 3, 6, 19, 8, + 8, 6, 19, 16, + 8, 6, 16, 9, + 9, 6, 16, 5, + 9, 5, 16, 17, + }, + // 0b10111101 case 189 + { + 14, 0, 1, 10, + 14, 12, 0, 10, + 14, 15, 12, 10, + 12, 0, 10, 6, + 10, 15, 12, 6, + 6, 15, 12, 19, + 12, 0, 19, 16, + 0, 6, 19, 16, + 0, 6, 16, 5, + 0, 5, 16, 9, + 16, 9, 5, 17, + }, + // 0b10111110 case 190 + { + 0, 15, 3, 8, + 0, 14, 15, 8, + 0, 13, 14, 8, + 8, 14, 15, 16, + 14, 15, 16, 19, + 13, 14, 8, 16, + 13, 14, 16, 17, + 14, 16, 17, 5, + 14, 16, 5, 10, + 10, 16, 5, 6, + 14, 19, 16, 10, + 10, 19, 16, 6, + }, + // 0b10111111 case 191 + { + 13, 15, 12, 16, + 13, 14, 15, 16, + 13, 14, 16, 17, + 14, 15, 16, 19, + 14, 16, 17, 5, + 14, 19, 16, 6, + 14, 6, 16, 10, + 14, 16, 5, 10, + 10, 6, 16, 5, + }, + // 0b11000000 case 192 + { + 10, 11, 5, 18, + 18, 11, 5, 7, + 11, 7, 18, 19, + }, + // 0b11000001 case 193 + { + 3, 12, 0, 8, + 5, 10, 11, 18, + 5, 18, 11, 7, + 11, 7, 18, 19, + }, + // 0b11000010 case 194 + { + 0, 13, 1, 9, + 10, 11, 5, 18, + 11, 7, 5, 18, + 11, 7, 18, 19, + }, + // 0b11000011 case 195 + { + 12, 1, 3, 8, + 12, 13, 1, 8, + 13, 1, 8, 9, + 10, 11, 5, 18, + 11, 7, 5, 18, + 11, 7, 18, 19, + }, + // 0b11000100 case 196 + { + 1, 14, 2, 7, + 1, 14, 7, 5, + 14, 2, 5, 18, + 2, 7, 5, 18, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11000101 case 197 + { + 1, 14, 2, 7, + 1, 14, 7, 5, + 14, 2, 5, 18, + 2, 7, 5, 18, + 2, 7, 18, 11, + 11, 7, 18, 19, + 3, 12, 0, 8, + }, + // 0b11000110 case 198 + { + 0, 13, 2, 9, + 13, 14, 2, 9, + 14, 2, 9, 5, + 14, 2, 5, 18, + 2, 9, 5, 7, + 2, 5, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11000111 case 199 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 8, 13, 2, 9, + 13, 14, 2, 9, + 9, 14, 2, 5, + 14, 2, 5, 18, + 2, 5, 18, 7, + 7, 18, 2, 11, + 18, 11, 7, 19, + }, + // 0b11001000 case 200 + { + 2, 15, 3, 10, + 15, 3, 10, 5, + 5, 10, 15, 18, + 5, 15, 3, 7, + 5, 18, 15, 7, + 18, 15, 7, 19, + }, + // 0b11001001 case 201 + { + 12, 0, 2, 8, + 15, 12, 2, 8, + 2, 15, 8, 7, + 2, 15, 7, 19, + 2, 7, 8, 5, + 2, 19, 7, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001010 case 202 + { + 0, 13, 1, 9, + 2, 15, 3, 5, + 15, 3, 5, 7, + 2, 15, 7, 19, + 2, 7, 5, 19, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001011 case 203 + { + 2, 13, 1, 9, + 2, 12, 13, 9, + 2, 12, 9, 8, + 2, 15, 12, 8, + 2, 15, 8, 7, + 2, 15, 7, 19, + 2, 19, 7, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11001100 case 204 + { + 1, 14, 3, 5, + 14, 15, 3, 5, + 15, 3, 5, 7, + 14, 15, 5, 18, + 15, 7, 5, 18, + 15, 7, 18, 19, + }, + // 0b11001101 case 205 + { + 1, 12, 0, 8, + 1, 15, 12, 8, + 1, 15, 8, 7, + 1, 14, 15, 7, + 14, 15, 7, 19, + 14, 7, 1, 5, + 14, 7, 5, 19, + 14, 19, 5, 18, + }, + // 0b11001110 case 206 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 5, + 14, 15, 3, 5, + 14, 15, 5, 18, + 15, 3, 5, 7, + 15, 7, 5, 18, + 15, 7, 18, 19, + }, + // 0b11001111 case 207 + { + 15, 12, 13, 8, + 13, 15, 8, 9, + 14, 15, 13, 9, + 15, 8, 9, 7, + 14, 15, 9, 7, + 14, 7, 9, 5, + 15, 7, 14, 19, + 14, 19, 7, 5, + 14, 19, 5, 18, + }, + // 0b11010000 case 208 + { + 10, 11, 8, 4, + 10, 11, 4, 5, + 11, 8, 4, 16, + 11, 5, 10, 18, + 11, 16, 4, 19, + 11, 4, 5, 19, + 11, 5, 18, 19, + }, + // 0b11010001 case 209 + { + 3, 12, 0, 5, + 12, 0, 5, 4, + 12, 4, 5, 16, + 3, 12, 5, 16, + 3, 16, 5, 11, + 11, 16, 5, 19, + 11, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11010010 case 210 + { + 0, 13, 1, 9, + 10, 11, 8, 4, + 10, 11, 4, 5, + 10, 11, 5, 18, + 11, 8, 4, 16, + 11, 5, 18, 19, + 11, 4, 5, 19, + 11, 16, 4, 19, + }, + // 0b11010011 case 211 + { + 3, 13, 1, 4, + 13, 1, 4, 9, + 3, 12, 13, 4, + 3, 12, 4, 16, + 3, 16, 4, 11, + 11, 16, 4, 19, + 10, 11, 4, 19, + 10, 19, 4, 5, + 10, 19, 5, 18, + }, + // 0b11010100 case 212 + { + 1, 14, 2, 5, + 14, 2, 5, 18, + 2, 5, 18, 4, + 2, 4, 18, 8, + 2, 8, 18, 11, + 18, 8, 4, 16, + 18, 8, 16, 11, + 18, 11, 16, 19, + }, + // 0b11010101 case 213 + { + 12, 0, 3, 11, + 12, 0, 11, 4, + 12, 4, 11, 16, + 4, 11, 16, 19, + 11, 19, 4, 5, + 11, 19, 5, 18, + 1, 14, 2, 11, + 1, 14, 11, 5, + 14, 11, 5, 18, + }, + // 0b11010110 case 214 + { + 13, 2, 0, 5, + 0, 13, 5, 9, + 13, 14, 2, 5, + 5, 14, 2, 18, + 5, 18, 2, 11, + 5, 18, 11, 19, + 5, 11, 8, 19, + 8, 5, 19, 4, + 8, 4, 19, 16, + }, + // 0b11010111 case 215 + { + 3, 2, 11, 19, + 3, 14, 2, 19, + 3, 12, 14, 19, + 12, 13, 14, 19, + 12, 13, 19, 16, + 13, 14, 16, 9, + 9, 14, 16, 4, + 14, 19, 16, 4, + 14, 4, 9, 5, + 14, 19, 4, 5, + 14, 19, 5, 18, + }, + // 0b11011000 case 216 + { + 2, 15, 3, 10, + 15, 3, 10, 8, + 10, 15, 8, 5, + 15, 8, 5, 4, + 15, 5, 10, 18, + 15, 8, 4, 16, + 15, 4, 5, 19, + 15, 16, 4, 19, + 15, 5, 18, 19, + }, + // 0b11011001 case 217 + { + 2, 12, 0, 4, + 2, 15, 12, 4, + 15, 12, 4, 16, + 2, 15, 16, 19, + 2, 19, 16, 4, + 2, 19, 4, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11011010 case 218 + { + 0, 13, 1, 9, + 2, 15, 3, 10, + 15, 3, 10, 8, + 10, 15, 8, 5, + 5, 15, 8, 4, + 15, 5, 10, 18, + 15, 4, 5, 19, + 15, 8, 4, 16, + 15, 5, 18, 19, + 15, 16, 4, 19, + }, + // 0b11011011 case 219 + { + 13, 1, 2, 9, + 12, 13, 2, 9, + 12, 2, 15, 9, + 15, 9, 2, 4, + 15, 12, 9, 4, + 15, 12, 4, 16, + 15, 16, 2, 19, + 2, 16, 4, 19, + 2, 19, 4, 5, + 2, 19, 5, 10, + 10, 19, 5, 18, + }, + // 0b11011100 case 220 + { + 1, 14, 3, 5, + 14, 15, 3, 5, + 14, 15, 5, 18, + 15, 3, 5, 8, + 15, 8, 5, 4, + 15, 8, 4, 16, + 15, 16, 4, 19, + 15, 4, 5, 19, + 15, 5, 18, 19, + }, + // 0b11011101 case 221 + { + 14, 0, 1, 5, + 14, 15, 0, 5, + 14, 15, 5, 18, + 15, 12, 0, 5, + 12, 0, 5, 4, + 15, 12, 18, 19, + 12, 4, 5, 16, + 12, 5, 18, 16, + 12, 18, 19, 16, + }, + // 0b11011110 case 222 + { + 13, 3, 0, 9, + 13, 14, 3, 9, + 14, 3, 9, 5, + 14, 3, 5, 18, + 14, 15, 3, 18, + 15, 3, 18, 19, + 3, 18, 19, 5, + 3, 5, 19, 4, + 3, 4, 19, 8, + 8, 4, 19, 16, + }, + // 0b11011111 case 223 + { + 14, 12, 13, 9, + 14, 15, 12, 9, + 14, 15, 9, 5, + 14, 15, 5, 18, + 15, 9, 5, 4, + 15, 12, 9, 4, + 15, 12, 4, 16, + 15, 16, 4, 19, + 15, 4, 5, 19, + 15, 5, 18, 19, + }, + // 0b11100000 case 224 + { + 9, 10, 11, 7, + 9, 10, 7, 4, + 10, 11, 7, 19, + 10, 4, 9, 17, + 10, 19, 7, 18, + 10, 7, 4, 18, + 10, 4, 17, 18, + }, + // 0b11100001 case 225 + { + 3, 12, 0, 8, + 9, 10, 11, 7, + 9, 10, 7, 4, + 10, 11, 7, 19, + 10, 4, 9, 17, + 10, 19, 7, 18, + 10, 7, 4, 18, + 10, 4, 17, 18, + }, + // 0b11100010 case 226 + { + 0, 13, 1, 4, + 13, 1, 4, 17, + 1, 4, 17, 10, + 10, 4, 17, 18, + 1, 4, 10, 11, + 10, 11, 4, 18, + 18, 11, 4, 7, + 18, 11, 7, 19, + }, + // 0b11100011 case 227 + { + 12, 1, 3, 4, + 12, 4, 3, 8, + 12, 13, 1, 4, + 13, 1, 4, 17, + 1, 4, 17, 10, + 10, 4, 17, 18, + 10, 11, 4, 18, + 11, 4, 18, 7, + 11, 7, 18, 19, + }, + // 0b11100100 case 228 + { + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 4, + 14, 11, 4, 7, + 14, 11, 7, 19, + 14, 4, 9, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + }, + // 0b11100101 case 229 + { + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 4, + 14, 11, 4, 7, + 14, 11, 7, 19, + 14, 4, 9, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + 3, 12, 0, 8, + }, + // 0b11100110 case 230 + { + 0, 13, 2, 4, + 13, 14, 2, 4, + 13, 14, 4, 17, + 14, 2, 17, 18, + 2, 4, 17, 18, + 2, 4, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11100111 case 231 + { + 12, 2, 3, 8, + 12, 13, 2, 8, + 13, 2, 8, 4, + 13, 14, 2, 4, + 13, 14, 4, 17, + 14, 2, 17, 18, + 2, 4, 17, 18, + 2, 4, 18, 7, + 2, 7, 18, 11, + 11, 7, 18, 19, + }, + // 0b11101000 case 232 + { + 2, 15, 3, 7, + 2, 15, 7, 19, + 2, 19, 7, 4, + 2, 19, 4, 9, + 9, 19, 4, 17, + 2, 19, 9, 10, + 9, 10, 19, 17, + 10, 19, 17, 18, + }, + // 0b11101001 case 233 + { + 2, 12, 0, 7, + 12, 0, 7, 8, + 2, 15, 12, 7, + 2, 15, 7, 19, + 2, 19, 7, 10, + 10, 19, 7, 18, + 9, 10, 7, 18, + 9, 18, 7, 4, + 9, 18, 4, 17, + }, + // 0b11101010 case 234 + { + 0, 13, 1, 10, + 0, 13, 10, 17, + 0, 17, 10, 4, + 10, 4, 17, 18, + 10, 7, 4, 18, + 2, 15, 3, 10, + 15, 3, 10, 7, + 10, 15, 7, 18, + 15, 7, 18, 19, + }, + // 0b11101011 case 235 + { + 13, 1, 2, 10, + 13, 2, 15, 10, + 13, 15, 12, 10, + 12, 13, 10, 18, + 10, 15, 12, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 8, + 12, 18, 19, 8, + 8, 17, 18, 4, + 8, 4, 18, 7, + 19, 8, 18, 7, + }, + // 0b11101100 case 236 + { + 1, 15, 3, 7, + 1, 14, 15, 7, + 14, 15, 7, 19, + 1, 14, 19, 18, + 1, 18, 19, 7, + 1, 18, 7, 4, + 1, 18, 4, 9, + 9, 18, 4, 17, + }, + // 0b11101101 case 237 + { + 1, 12, 0, 8, + 1, 15, 12, 8, + 1, 14, 15, 8, + 1, 14, 8, 7, + 14, 15, 8, 7, + 14, 15, 7, 19, + 1, 14, 19, 18, + 1, 18, 19, 7, + 1, 18, 7, 4, + 4, 1, 18, 9, + 9, 18, 4, 17, + }, + // 0b11101110 case 238 + { + 13, 3, 0, 4, + 13, 15, 3, 4, + 15, 3, 4, 7, + 13, 14, 15, 7, + 13, 14, 7, 4, + 14, 15, 7, 19, + 13, 14, 4, 17, + 14, 19, 7, 18, + 14, 7, 4, 18, + 14, 4, 17, 18, + }, + // 0b11101111 case 239 + { + 14, 15, 12, 18, + 12, 13, 14, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 8, + 12, 18, 19, 8, + 8, 17, 18, 4, + 18, 8, 4, 7, + 19, 8, 18, 7, + }, + // 0b11110000 case 240 + { + 9, 10, 11, 18, + 8, 9, 11, 18, + 8, 9, 18, 17, + 18, 11, 8, 19, + 8, 17, 18, 16, + 8, 18, 19, 16, + }, + // 0b11110001 case 241 + { + 3, 12, 0, 11, + 12, 0, 11, 9, + 11, 12, 9, 16, + 9, 10, 11, 16, + 10, 11, 16, 19, + 9, 10, 16, 17, + 10, 19, 16, 18, + 10, 16, 17, 18, + }, + // 0b11110010 case 242 + { + 0, 13, 1, 10, + 0, 13, 10, 8, + 8, 13, 10, 17, + 8, 17, 10, 18, + 8, 17, 18, 16, + 11, 8, 10, 16, + 11, 16, 10, 18, + 11, 16, 18, 19, + }, + // 0b11110011 case 243 + { + 12, 1, 3, 11, + 12, 13, 1, 11, + 13, 1, 11, 10, + 11, 13, 10, 18, + 11, 13, 18, 19, + 12, 13, 11, 19, + 12, 13, 18, 17, + 12, 17, 18, 19, + 12, 17, 19, 16, + }, + // 0b11110100 case 244 + { + 1, 14, 2, 11, + 1, 14, 11, 9, + 14, 11, 9, 18, + 11, 9, 18, 19, + 9, 18, 19, 17, + 8, 9, 11, 19, + 8, 9, 19, 17, + 8, 17, 19, 16, + }, + // 0b11110101 case 245 + { + 3, 12, 0, 11, + 12, 0, 11, 9, + 1, 14, 2, 9, + 14, 2, 9, 11, + 14, 11, 9, 18, + 12, 9, 11, 19, + 9, 18, 11, 19, + 12, 9, 19, 16, + 9, 18, 19, 17, + 9, 19, 16, 17, + }, + // 0b11110110 case 246 + { + 0, 13, 2, 8, + 13, 2, 8, 11, + 13, 14, 2, 11, + 13, 14, 11, 19, + 13, 11, 8, 19, + 13, 19, 8, 16, + 13, 14, 19, 18, + 13, 19, 16, 17, + 13, 18, 19, 17, + }, + // 0b11110111 case 247 + { + 12, 2, 3, 11, + 12, 14, 2, 11, + 12, 13, 14, 11, + 13, 14, 11, 18, + 12, 13, 11, 18, + 12, 18, 11, 19, + 12, 13, 18, 17, + 12, 18, 19, 16, + 12, 17, 18, 16, + }, + // 0b11111000 case 248 + { + 2, 15, 3, 10, + 15, 3, 10, 8, + 15, 8, 10, 19, + 8, 10, 19, 16, + 16, 10, 19, 18, + 8, 9, 10, 16, + 16, 9, 10, 18, + 9, 18, 16, 17, + }, + // 0b11111001 case 249 + { + 2, 15, 0, 10, + 15, 12, 0, 10, + 12, 0, 10, 9, + 10, 15, 9, 18, + 15, 12, 9, 18, + 12, 9, 18, 17, + 18, 15, 12, 19, + 12, 17, 18, 19, + 12, 17, 19, 16, + }, + // 0b11111010 case 250 + { + 0, 13, 1, 8, + 13, 1, 8, 10, + 8, 13, 10, 16, + 13, 10, 16, 18, + 13, 18, 16, 17, + 2, 15, 3, 10, + 15, 3, 10, 8, + 15, 8, 10, 18, + 15, 8, 18, 16, + 15, 16, 18, 19, + }, + // 0b11111011 case 251 + { + 2, 1, 10, 18, + 2, 15, 1, 18, + 15, 13, 1, 18, + 15, 12, 13, 18, + 15, 12, 18, 19, + 12, 13, 18, 17, + 12, 17, 18, 16, + 12, 18, 19, 16, + }, + // 0b11111100 case 252 + { + 1, 14, 3, 9, + 14, 3, 9, 8, + 14, 15, 3, 8, + 9, 14, 8, 17, + 14, 15, 8, 17, + 17, 15, 8, 16, + 14, 15, 17, 18, + 15, 17, 18, 19, + 15, 16, 17, 19, + }, + // 0b11111101 case 253 + { + 1, 0, 9, 17, + 14, 0, 1, 17, + 14, 12, 0, 17, + 14, 15, 12, 17, + 14, 15, 17, 18, + 15, 12, 17, 16, + 15, 17, 18, 19, + 15, 16, 17, 19, + }, + // 0b11111110 case 254 + { + 0, 3, 8, 16, + 13, 3, 0, 16, + 13, 15, 3, 16, + 13, 14, 15, 16, + 13, 14, 16, 17, + 14, 15, 16, 19, + 14, 16, 17, 18, + 14, 19, 16, 18, + }, + // 0b11111111 case 255 + { + 12, 14, 15, 19, + 12, 13, 14, 19, + 12, 13, 19, 16, + 13, 14, 19, 18, + 13, 18, 19, 17, + 13, 19, 16, 17, + }, +} + +//----------------------------------------------------------------------------- diff --git a/render/marchfelogic.go b/render/marchfelogic.go new file mode 100644 index 000000000..a7b50924e --- /dev/null +++ b/render/marchfelogic.go @@ -0,0 +1,350 @@ +package render + +import ( + "fmt" + + "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape Shape) []*Fe { + var fes []*Fe + var tmp []*Fe // Declare here to avoid redeclaring inside each loop iteration. + size := box.Size() + base := box.Min + steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) + inc := size.Div(conv.V3iToV3(steps)) + + // start the evaluation routines + evalRoutines() + + // create the SDF layer cache + l := newLayerXY(base, inc, steps) + // evaluate the SDF for z = 0 + l.Evaluate(s, 0) + + nx, ny, nz := steps.X, steps.Y, steps.Z + dx, dy, dz := inc.X, inc.Y, inc.Z + + var p v3.Vec + p.Z = base.Z + for z := 0; z < nz; z++ { + // read the z + 1 layer + l.Evaluate(s, z+1) + // process all cubes in the z and z + 1 layers + p.X = base.X + for x := 0; x < nx; x++ { + p.Y = base.Y + for y := 0; y < ny; y++ { + x0, y0, z0 := p.X, p.Y, p.Z + x1, y1, z1 := x0+dx, y0+dy, z0+dz + corners := [8]v3.Vec{ + {x0, y0, z0}, + {x1, y0, z0}, + {x1, y1, z0}, + {x0, y1, z0}, + {x0, y0, z1}, + {x1, y0, z1}, + {x1, y1, z1}, + {x0, y1, z1}} + values := [8]float64{ + l.Get(x, y, 0), + l.Get(x+1, y, 0), + l.Get(x+1, y+1, 0), + l.Get(x, y+1, 0), + l.Get(x, y, 1), + l.Get(x+1, y, 1), + l.Get(x+1, y+1, 1), + l.Get(x, y+1, 1), + } + + switch order { + case Linear: + { + switch shape { + case Hexahedral: + { + fes = append(fes, mcToHex8(corners, values, 0, x, y, z)...) + } + case Tetrahedral: + { + fes = append(fes, mcToTet4(corners, values, 0, x, y, z)...) + } + case Both: + { + tmp = mcToHex8(corners, values, 0, x, y, z) + if len(tmp) < 1 { + tmp = mcToTet4(corners, values, 0, x, y, z) + } + fes = append(fes, tmp...) + + } + } + } + case Quadratic: + { + switch shape { + case Hexahedral: + { + fes = append(fes, mcToHex20(corners, values, 0, x, y, z)...) + } + case Tetrahedral: + { + fes = append(fes, mcToTet10(corners, values, 0, x, y, z)...) + } + case Both: + { + tmp = mcToHex20(corners, values, 0, x, y, z) + if len(tmp) < 1 { + tmp = mcToTet10(corners, values, 0, x, y, z) + } + fes = append(fes, tmp...) + + } + } + } + } + p.Y += dy + } + p.X += dx + } + p.Z += dz + } + + return fes +} + +//----------------------------------------------------------------------------- + +func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { + result := make([]*Fe, 0) + + anyPositive := false + for i := 0; i < 8; i++ { + if v[i] > 0 { + anyPositive = true + break + } + } + + // Create a finite element if all 8 values are non-positive. + // Finite element is inside the 3D model if all values are non-positive. + // Of course, some spaces are missed by this approach. + // + // TODO: Come up with a more sophisticated approach? + + if !anyPositive { + fe := Fe{ + V: make([]v3.Vec, 8), + X: layerX, + Y: layerY, + Z: layerZ, + } + + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + + fe.V[7] = p[7] + fe.V[6] = p[6] + fe.V[5] = p[5] + fe.V[4] = p[4] + fe.V[3] = p[3] + fe.V[2] = p[2] + fe.V[1] = p[1] + fe.V[0] = p[0] + result = append(result, &fe) + } + + return result +} + +//----------------------------------------------------------------------------- + +func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { + result := make([]*Fe, 0) + + anyPositive := false + for i := 0; i < 8; i++ { + if v[i] > 0 { + anyPositive = true + break + } + } + + // Create a finite element if all 8 values are non-positive. + // Finite element is inside the 3D model if all values are non-positive. + // Of course, some spaces are missed by this approach. + // + // TODO: Come up with a more sophisticated approach? + + if !anyPositive { + fe := Fe{ + V: make([]v3.Vec, 20), + X: layerX, + Y: layerY, + Z: layerZ, + } + + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + + // Points on cube corners: + fe.V[7] = p[7] + fe.V[6] = p[6] + fe.V[5] = p[5] + fe.V[4] = p[4] + fe.V[3] = p[3] + fe.V[2] = p[2] + fe.V[1] = p[1] + fe.V[0] = p[0] + + // Points on cube edges: + fe.V[8] = p[0].Add(p[1]).MulScalar(0.5) + fe.V[9] = p[1].Add(p[2]).MulScalar(0.5) + fe.V[10] = p[2].Add(p[3]).MulScalar(0.5) + fe.V[11] = p[3].Add(p[0]).MulScalar(0.5) + + fe.V[12] = p[4].Add(p[5]).MulScalar(0.5) + fe.V[13] = p[5].Add(p[6]).MulScalar(0.5) + fe.V[14] = p[6].Add(p[7]).MulScalar(0.5) + fe.V[15] = p[7].Add(p[4]).MulScalar(0.5) + + fe.V[16] = p[0].Add(p[4]).MulScalar(0.5) + fe.V[17] = p[1].Add(p[5]).MulScalar(0.5) + fe.V[18] = p[2].Add(p[6]).MulScalar(0.5) + fe.V[19] = p[3].Add(p[7]).MulScalar(0.5) + + result = append(result, &fe) + } + + return result +} + +//----------------------------------------------------------------------------- + +func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { + // which of the 0..255 patterns do we have? + index := 0 + for i := 0; i < 8; i++ { + if v[i] < x { + index |= 1 << uint(i) + } + } + + // work out the interpolated points on the edges + var points [12]v3.Vec + for i := 0; i < 12; i++ { + bit := 1 << uint(i) + if mcEdgeTable[index]&bit != 0 { + a := mcPairTable[i][0] + b := mcPairTable[i][1] + points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) + } + } + + // Create the tetrahedra. + table := mcTetrahedronTable[index] + count := len(table) / 4 + result := make([]*Fe, 0, count) + for i := 0; i < count; i++ { + t := Fe{ + V: make([]v3.Vec, 4), + X: layerX, + Y: layerY, + Z: layerZ, + } + + t.V[0] = point(points, p, table[i*4+0]) + t.V[1] = point(points, p, table[i*4+1]) + t.V[2] = point(points, p, table[i*4+2]) + t.V[3] = point(points, p, table[i*4+3]) + degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) + flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) + + // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. + // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: + bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) + if !degenerated && !bad && !flat { + result = append(result, &t) + } else { + fmt.Println("Bad element: tet4") + fmt.Println("Non-positive Jacobian determinant? ", bad) + fmt.Println("Jacobian determinant: ", jacobianDeterminant) + fmt.Println("Almost flat? ", flat) + fmt.Println("Volume: ", volume) + fmt.Println("Degenerated? ", degenerated) + } + } + + return result +} + +//----------------------------------------------------------------------------- + +func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { + // which of the 0..255 patterns do we have? + index := 0 + for i := 0; i < 8; i++ { + if v[i] < x { + index |= 1 << uint(i) + } + } + + // work out the interpolated points on the edges + var points [12]v3.Vec + for i := 0; i < 12; i++ { + bit := 1 << uint(i) + if mcEdgeTable[index]&bit != 0 { + a := mcPairTable[i][0] + b := mcPairTable[i][1] + points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) + } + } + + // Create the tetrahedra. + table := mcTetrahedronTable[index] + count := len(table) / 4 + result := make([]*Fe, 0, count) + for i := 0; i < count; i++ { + t := Fe{ + V: make([]v3.Vec, 10), + X: layerX, + Y: layerY, + Z: layerZ, + } + + // Points on tetrahedron corners. + t.V[0] = point(points, p, table[i*4+0]) + t.V[1] = point(points, p, table[i*4+1]) + t.V[2] = point(points, p, table[i*4+2]) + t.V[3] = point(points, p, table[i*4+3]) + degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) + flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) + // Points on tetrahedron edges. + // Followoing CalculiX node numbering. + t.V[5-1] = t.V[1-1].Add(t.V[2-1]).MulScalar(0.5) + t.V[6-1] = t.V[2-1].Add(t.V[3-1]).MulScalar(0.5) + t.V[7-1] = t.V[1-1].Add(t.V[3-1]).MulScalar(0.5) + t.V[8-1] = t.V[1-1].Add(t.V[4-1]).MulScalar(0.5) + t.V[9-1] = t.V[2-1].Add(t.V[4-1]).MulScalar(0.5) + t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) + // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. + // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: + bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) + if !degenerated && !bad && !flat { + result = append(result, &t) + } else { + fmt.Println("Bad element: tet10") + fmt.Println("Non-positive Jacobian determinant? ", bad) + fmt.Println("Jacobian determinant: ", jacobianDeterminant) + fmt.Println("Almost flat? ", flat) + fmt.Println("Volume: ", volume) + fmt.Println("Degenerated? ", degenerated) + } + } + + return result +} + +//----------------------------------------------------------------------------- diff --git a/render/marchhex20.go b/render/marchhex20.go deleted file mode 100644 index 3f88d58cd..000000000 --- a/render/marchhex20.go +++ /dev/null @@ -1,133 +0,0 @@ -package render - -import ( - "github.com/deadsy/sdfx/sdf" - "github.com/deadsy/sdfx/vec/conv" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -//----------------------------------------------------------------------------- - -func marchingCubesHex20(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { - - var fes []*Fe - size := box.Size() - base := box.Min - steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) - inc := size.Div(conv.V3iToV3(steps)) - - // start the evaluation routines - evalRoutines() - - // create the SDF layer cache - l := newLayerYZ(base, inc, steps) - // evaluate the SDF for x = 0 - l.Evaluate(s, 0) - - nx, ny, nz := steps.X, steps.Y, steps.Z - dx, dy, dz := inc.X, inc.Y, inc.Z - - var p v3.Vec - p.X = base.X - for x := 0; x < nx; x++ { - // read the x + 1 layer - l.Evaluate(s, x+1) - // process all cubes in the x and x + 1 layers - p.Y = base.Y - for y := 0; y < ny; y++ { - p.Z = base.Z - for z := 0; z < nz; z++ { - x0, y0, z0 := p.X, p.Y, p.Z - x1, y1, z1 := x0+dx, y0+dy, z0+dz - corners := [8]v3.Vec{ - {x0, y0, z0}, - {x1, y0, z0}, - {x1, y1, z0}, - {x0, y1, z0}, - {x0, y0, z1}, - {x1, y0, z1}, - {x1, y1, z1}, - {x0, y1, z1}} - values := [8]float64{ - l.Get(0, y, z), - l.Get(1, y, z), - l.Get(1, y+1, z), - l.Get(0, y+1, z), - l.Get(0, y, z+1), - l.Get(1, y, z+1), - l.Get(1, y+1, z+1), - l.Get(0, y+1, z+1)} - fes = append(fes, mcToHex20(corners, values, 0, x, y, z)...) - p.Z += dz - } - p.Y += dy - } - p.X += dx - } - - return fes -} - -//----------------------------------------------------------------------------- - -func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { - result := make([]*Fe, 0) - - anyPositive := false - for i := 0; i < 8; i++ { - if v[i] > 0 { - anyPositive = true - break - } - } - - // Create a finite element if all 8 values are non-positive. - // Finite element is inside the 3D model if all values are non-positive. - // Of course, some spaces are missed by this approach. - // - // TODO: Come up with a more sophisticated approach? - - if !anyPositive { - fe := Fe{ - V: make([]v3.Vec, 20), - X: layerX, - Y: layerY, - Z: layerZ, - } - - // Refer to CalculiX solver documentation: - // http://www.dhondt.de/ccx_2.20.pdf - - // Points on cube corners: - fe.V[7] = p[7] - fe.V[6] = p[6] - fe.V[5] = p[5] - fe.V[4] = p[4] - fe.V[3] = p[3] - fe.V[2] = p[2] - fe.V[1] = p[1] - fe.V[0] = p[0] - - // Points on cube edges: - fe.V[8] = p[0].Add(p[1]).MulScalar(0.5) - fe.V[9] = p[1].Add(p[2]).MulScalar(0.5) - fe.V[10] = p[2].Add(p[3]).MulScalar(0.5) - fe.V[11] = p[3].Add(p[0]).MulScalar(0.5) - - fe.V[12] = p[4].Add(p[5]).MulScalar(0.5) - fe.V[13] = p[5].Add(p[6]).MulScalar(0.5) - fe.V[14] = p[6].Add(p[7]).MulScalar(0.5) - fe.V[15] = p[7].Add(p[4]).MulScalar(0.5) - - fe.V[16] = p[0].Add(p[4]).MulScalar(0.5) - fe.V[17] = p[1].Add(p[5]).MulScalar(0.5) - fe.V[18] = p[2].Add(p[6]).MulScalar(0.5) - fe.V[19] = p[3].Add(p[7]).MulScalar(0.5) - - result = append(result, &fe) - } - - return result -} - -//----------------------------------------------------------------------------- diff --git a/render/marchhex20tet10.go b/render/marchhex20tet10.go deleted file mode 100644 index f8a1224ed..000000000 --- a/render/marchhex20tet10.go +++ /dev/null @@ -1,83 +0,0 @@ -package render - -import ( - "github.com/deadsy/sdfx/sdf" - "github.com/deadsy/sdfx/vec/conv" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -//----------------------------------------------------------------------------- - -func marchingCubesHex20Tet10(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { - var fes []*Fe - size := box.Size() - base := box.Min - steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) - inc := size.Div(conv.V3iToV3(steps)) - - // start the evaluation routines - evalRoutines() - - // create the SDF layer cache - l := newLayerXY(base, inc, steps) - // evaluate the SDF for z = 0 - l.Evaluate(s, 0) - - nx, ny, nz := steps.X, steps.Y, steps.Z - dx, dy, dz := inc.X, inc.Y, inc.Z - - var p v3.Vec - p.Z = base.Z - for z := 0; z < nz; z++ { - // read the z + 1 layer - l.Evaluate(s, z+1) - // process all cubes in the z and z + 1 layers - p.X = base.X - for x := 0; x < nx; x++ { - p.Y = base.Y - for y := 0; y < ny; y++ { - x0, y0, z0 := p.X, p.Y, p.Z - x1, y1, z1 := x0+dx, y0+dy, z0+dz - corners := [8]v3.Vec{ - {x0, y0, z0}, - {x1, y0, z0}, - {x1, y1, z0}, - {x0, y1, z0}, - {x0, y0, z1}, - {x1, y0, z1}, - {x1, y1, z1}, - {x0, y1, z1}} - values := [8]float64{ - l.Get(x, y, 0), - l.Get(x+1, y, 0), - l.Get(x+1, y+1, 0), - l.Get(x, y+1, 0), - l.Get(x, y, 1), - l.Get(x+1, y, 1), - l.Get(x+1, y+1, 1), - l.Get(x, y+1, 1), - } - fes = append(fes, mcToHex20Tet10(corners, values, 0, x, y, z)...) - p.Y += dy - } - p.X += dx - } - p.Z += dz - } - - return fes -} - -//----------------------------------------------------------------------------- - -func mcToHex20Tet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { - result := mcToHex20(p, v, x, layerX, layerY, layerZ) - - if len(result) < 1 { - result = mcToTet10(p, v, x, layerX, layerY, layerZ) - } - - return result -} - -//----------------------------------------------------------------------------- diff --git a/render/marchhex8.go b/render/marchhex8.go deleted file mode 100644 index a13ac46ac..000000000 --- a/render/marchhex8.go +++ /dev/null @@ -1,115 +0,0 @@ -package render - -import ( - "github.com/deadsy/sdfx/sdf" - "github.com/deadsy/sdfx/vec/conv" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -//----------------------------------------------------------------------------- - -func marchingCubesHex8(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { - - var fes []*Fe - size := box.Size() - base := box.Min - steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) - inc := size.Div(conv.V3iToV3(steps)) - - // start the evaluation routines - evalRoutines() - - // create the SDF layer cache - l := newLayerYZ(base, inc, steps) - // evaluate the SDF for x = 0 - l.Evaluate(s, 0) - - nx, ny, nz := steps.X, steps.Y, steps.Z - dx, dy, dz := inc.X, inc.Y, inc.Z - - var p v3.Vec - p.X = base.X - for x := 0; x < nx; x++ { - // read the x + 1 layer - l.Evaluate(s, x+1) - // process all cubes in the x and x + 1 layers - p.Y = base.Y - for y := 0; y < ny; y++ { - p.Z = base.Z - for z := 0; z < nz; z++ { - x0, y0, z0 := p.X, p.Y, p.Z - x1, y1, z1 := x0+dx, y0+dy, z0+dz - corners := [8]v3.Vec{ - {x0, y0, z0}, - {x1, y0, z0}, - {x1, y1, z0}, - {x0, y1, z0}, - {x0, y0, z1}, - {x1, y0, z1}, - {x1, y1, z1}, - {x0, y1, z1}} - values := [8]float64{ - l.Get(0, y, z), - l.Get(1, y, z), - l.Get(1, y+1, z), - l.Get(0, y+1, z), - l.Get(0, y, z+1), - l.Get(1, y, z+1), - l.Get(1, y+1, z+1), - l.Get(0, y+1, z+1)} - fes = append(fes, mcToHex8(corners, values, 0, x, y, z)...) - p.Z += dz - } - p.Y += dy - } - p.X += dx - } - - return fes -} - -//----------------------------------------------------------------------------- - -func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { - result := make([]*Fe, 0) - - anyPositive := false - for i := 0; i < 8; i++ { - if v[i] > 0 { - anyPositive = true - break - } - } - - // Create a finite element if all 8 values are non-positive. - // Finite element is inside the 3D model if all values are non-positive. - // Of course, some spaces are missed by this approach. - // - // TODO: Come up with a more sophisticated approach? - - if !anyPositive { - fe := Fe{ - V: make([]v3.Vec, 8), - X: layerX, - Y: layerY, - Z: layerZ, - } - - // Refer to CalculiX solver documentation: - // http://www.dhondt.de/ccx_2.20.pdf - - fe.V[7] = p[7] - fe.V[6] = p[6] - fe.V[5] = p[5] - fe.V[4] = p[4] - fe.V[3] = p[3] - fe.V[2] = p[2] - fe.V[1] = p[1] - fe.V[0] = p[0] - result = append(result, &fe) - } - - return result -} - -//----------------------------------------------------------------------------- diff --git a/render/marchhex8tet4.go b/render/marchhex8tet4.go deleted file mode 100644 index c14f568f9..000000000 --- a/render/marchhex8tet4.go +++ /dev/null @@ -1,82 +0,0 @@ -package render - -import ( - "github.com/deadsy/sdfx/sdf" - "github.com/deadsy/sdfx/vec/conv" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -//----------------------------------------------------------------------------- - -func marchingCubesHex8Tet4(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { - var fes []*Fe - size := box.Size() - base := box.Min - steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) - inc := size.Div(conv.V3iToV3(steps)) - - // start the evaluation routines - evalRoutines() - - // create the SDF layer cache - l := newLayerYZ(base, inc, steps) - // evaluate the SDF for x = 0 - l.Evaluate(s, 0) - - nx, ny, nz := steps.X, steps.Y, steps.Z - dx, dy, dz := inc.X, inc.Y, inc.Z - - var p v3.Vec - p.X = base.X - for x := 0; x < nx; x++ { - // read the x + 1 layer - l.Evaluate(s, x+1) - // process all cubes in the x and x + 1 layers - p.Y = base.Y - for y := 0; y < ny; y++ { - p.Z = base.Z - for z := 0; z < nz; z++ { - x0, y0, z0 := p.X, p.Y, p.Z - x1, y1, z1 := x0+dx, y0+dy, z0+dz - corners := [8]v3.Vec{ - {x0, y0, z0}, - {x1, y0, z0}, - {x1, y1, z0}, - {x0, y1, z0}, - {x0, y0, z1}, - {x1, y0, z1}, - {x1, y1, z1}, - {x0, y1, z1}} - values := [8]float64{ - l.Get(0, y, z), - l.Get(1, y, z), - l.Get(1, y+1, z), - l.Get(0, y+1, z), - l.Get(0, y, z+1), - l.Get(1, y, z+1), - l.Get(1, y+1, z+1), - l.Get(0, y+1, z+1)} - fes = append(fes, mcToHex8Tet4(corners, values, 0, x, y, z)...) - p.Z += dz - } - p.Y += dy - } - p.X += dx - } - - return fes -} - -//----------------------------------------------------------------------------- - -func mcToHex8Tet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { - result := mcToHex8(p, v, x, layerX, layerY, layerZ) - - if len(result) < 1 { - result = mcToTet4(p, v, x, layerX, layerY, layerZ) - } - - return result -} - -//----------------------------------------------------------------------------- diff --git a/render/marchtet10.go b/render/marchtet10.go deleted file mode 100644 index 9d1f62f02..000000000 --- a/render/marchtet10.go +++ /dev/null @@ -1,140 +0,0 @@ -package render - -import ( - "fmt" - - "github.com/deadsy/sdfx/sdf" - "github.com/deadsy/sdfx/vec/conv" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -//----------------------------------------------------------------------------- - -func marchingCubesTet10(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { - var fes []*Fe - size := box.Size() - base := box.Min - steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) - inc := size.Div(conv.V3iToV3(steps)) - - // start the evaluation routines - evalRoutines() - - // create the SDF layer cache - l := newLayerXY(base, inc, steps) - // evaluate the SDF for z = 0 - l.Evaluate(s, 0) - - nx, ny, nz := steps.X, steps.Y, steps.Z - dx, dy, dz := inc.X, inc.Y, inc.Z - - var p v3.Vec - p.Z = base.Z - for z := 0; z < nz; z++ { - // read the z + 1 layer - l.Evaluate(s, z+1) - // process all cubes in the z and z + 1 layers - p.X = base.X - for x := 0; x < nx; x++ { - p.Y = base.Y - for y := 0; y < ny; y++ { - x0, y0, z0 := p.X, p.Y, p.Z - x1, y1, z1 := x0+dx, y0+dy, z0+dz - corners := [8]v3.Vec{ - {x0, y0, z0}, - {x1, y0, z0}, - {x1, y1, z0}, - {x0, y1, z0}, - {x0, y0, z1}, - {x1, y0, z1}, - {x1, y1, z1}, - {x0, y1, z1}} - values := [8]float64{ - l.Get(x, y, 0), - l.Get(x+1, y, 0), - l.Get(x+1, y+1, 0), - l.Get(x, y+1, 0), - l.Get(x, y, 1), - l.Get(x+1, y, 1), - l.Get(x+1, y+1, 1), - l.Get(x, y+1, 1), - } - fes = append(fes, mcToTet10(corners, values, 0, x, y, z)...) - p.Y += dy - } - p.X += dx - } - p.Z += dz - } - - return fes -} - -//----------------------------------------------------------------------------- - -func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { - // which of the 0..255 patterns do we have? - index := 0 - for i := 0; i < 8; i++ { - if v[i] < x { - index |= 1 << uint(i) - } - } - - // work out the interpolated points on the edges - var points [12]v3.Vec - for i := 0; i < 12; i++ { - bit := 1 << uint(i) - if mcEdgeTable[index]&bit != 0 { - a := mcPairTable[i][0] - b := mcPairTable[i][1] - points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) - } - } - - // Create the tetrahedra. - table := mcTetrahedronTable[index] - count := len(table) / 4 - result := make([]*Fe, 0, count) - for i := 0; i < count; i++ { - t := Fe{ - V: make([]v3.Vec, 10), - X: layerX, - Y: layerY, - Z: layerZ, - } - - // Points on tetrahedron corners. - t.V[0] = point(points, p, table[i*4+0]) - t.V[1] = point(points, p, table[i*4+1]) - t.V[2] = point(points, p, table[i*4+2]) - t.V[3] = point(points, p, table[i*4+3]) - degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) - flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) - // Points on tetrahedron edges. - // Followoing CalculiX node numbering. - t.V[5-1] = t.V[1-1].Add(t.V[2-1]).MulScalar(0.5) - t.V[6-1] = t.V[2-1].Add(t.V[3-1]).MulScalar(0.5) - t.V[7-1] = t.V[1-1].Add(t.V[3-1]).MulScalar(0.5) - t.V[8-1] = t.V[1-1].Add(t.V[4-1]).MulScalar(0.5) - t.V[9-1] = t.V[2-1].Add(t.V[4-1]).MulScalar(0.5) - t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) - // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. - // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) - if !degenerated && !bad && !flat { - result = append(result, &t) - } else { - fmt.Println("Bad element: tet10") - fmt.Println("Non-positive Jacobian determinant? ", bad) - fmt.Println("Jacobian determinant: ", jacobianDeterminant) - fmt.Println("Almost flat? ", flat) - fmt.Println("Volume: ", volume) - fmt.Println("Degenerated? ", degenerated) - } - } - - return result -} - -//----------------------------------------------------------------------------- diff --git a/render/marchtet4.go b/render/marchtet4.go deleted file mode 100644 index 27efe7dbf..000000000 --- a/render/marchtet4.go +++ /dev/null @@ -1,131 +0,0 @@ -package render - -import ( - "fmt" - - "github.com/deadsy/sdfx/sdf" - "github.com/deadsy/sdfx/vec/conv" - v3 "github.com/deadsy/sdfx/vec/v3" -) - -//----------------------------------------------------------------------------- - -func marchingCubesTet4(s sdf.SDF3, box sdf.Box3, step float64) []*Fe { - var fes []*Fe - size := box.Size() - base := box.Min - steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) - inc := size.Div(conv.V3iToV3(steps)) - - // start the evaluation routines - evalRoutines() - - // create the SDF layer cache - l := newLayerYZ(base, inc, steps) - // evaluate the SDF for x = 0 - l.Evaluate(s, 0) - - nx, ny, nz := steps.X, steps.Y, steps.Z - dx, dy, dz := inc.X, inc.Y, inc.Z - - var p v3.Vec - p.X = base.X - for x := 0; x < nx; x++ { - // read the x + 1 layer - l.Evaluate(s, x+1) - // process all cubes in the x and x + 1 layers - p.Y = base.Y - for y := 0; y < ny; y++ { - p.Z = base.Z - for z := 0; z < nz; z++ { - x0, y0, z0 := p.X, p.Y, p.Z - x1, y1, z1 := x0+dx, y0+dy, z0+dz - corners := [8]v3.Vec{ - {x0, y0, z0}, - {x1, y0, z0}, - {x1, y1, z0}, - {x0, y1, z0}, - {x0, y0, z1}, - {x1, y0, z1}, - {x1, y1, z1}, - {x0, y1, z1}} - values := [8]float64{ - l.Get(0, y, z), - l.Get(1, y, z), - l.Get(1, y+1, z), - l.Get(0, y+1, z), - l.Get(0, y, z+1), - l.Get(1, y, z+1), - l.Get(1, y+1, z+1), - l.Get(0, y+1, z+1)} - fes = append(fes, mcToTet4(corners, values, 0, x, y, z)...) - p.Z += dz - } - p.Y += dy - } - p.X += dx - } - - return fes -} - -//----------------------------------------------------------------------------- - -func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { - // which of the 0..255 patterns do we have? - index := 0 - for i := 0; i < 8; i++ { - if v[i] < x { - index |= 1 << uint(i) - } - } - - // work out the interpolated points on the edges - var points [12]v3.Vec - for i := 0; i < 12; i++ { - bit := 1 << uint(i) - if mcEdgeTable[index]&bit != 0 { - a := mcPairTable[i][0] - b := mcPairTable[i][1] - points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) - } - } - - // Create the tetrahedra. - table := mcTetrahedronTable[index] - count := len(table) / 4 - result := make([]*Fe, 0, count) - for i := 0; i < count; i++ { - t := Fe{ - V: make([]v3.Vec, 4), - X: layerX, - Y: layerY, - Z: layerZ, - } - - t.V[0] = point(points, p, table[i*4+0]) - t.V[1] = point(points, p, table[i*4+1]) - t.V[2] = point(points, p, table[i*4+2]) - t.V[3] = point(points, p, table[i*4+3]) - degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) - flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) - - // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. - // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) - if !degenerated && !bad && !flat { - result = append(result, &t) - } else { - fmt.Println("Bad element: tet4") - fmt.Println("Non-positive Jacobian determinant? ", bad) - fmt.Println("Jacobian determinant: ", jacobianDeterminant) - fmt.Println("Almost flat? ", flat) - fmt.Println("Volume: ", volume) - fmt.Println("Degenerated? ", degenerated) - } - } - - return result -} - -//----------------------------------------------------------------------------- From 45cc0c30cefd82aa679d4116d5fa94c03ecfb397 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 12:25:07 +0330 Subject: [PATCH 503/775] New func. Cleaner & more readable? --- render/marchfelogic.go | 99 ++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index a7b50924e..ca3850e30 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -10,7 +10,6 @@ import ( func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape Shape) []*Fe { var fes []*Fe - var tmp []*Fe // Declare here to avoid redeclaring inside each loop iteration. size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) @@ -58,58 +57,64 @@ func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape l.Get(x+1, y+1, 1), l.Get(x, y+1, 1), } + fes = append(fes, mcToFE(corners, values, 0, x, y, z, order, shape)...) + p.Y += dy + } + p.X += dx + } + p.Z += dz + } + + return fes +} + +//----------------------------------------------------------------------------- - switch order { - case Linear: - { - switch shape { - case Hexahedral: - { - fes = append(fes, mcToHex8(corners, values, 0, x, y, z)...) - } - case Tetrahedral: - { - fes = append(fes, mcToTet4(corners, values, 0, x, y, z)...) - } - case Both: - { - tmp = mcToHex8(corners, values, 0, x, y, z) - if len(tmp) < 1 { - tmp = mcToTet4(corners, values, 0, x, y, z) - } - fes = append(fes, tmp...) - - } - } +func mcToFE(corners [8]v3.Vec, values [8]float64, zero float64, x, y, z int, order Order, shape Shape) []*Fe { + var fes []*Fe + switch order { + case Linear: + { + switch shape { + case Hexahedral: + { + fes = append(fes, mcToHex8(corners, values, 0, x, y, z)...) + } + case Tetrahedral: + { + fes = append(fes, mcToTet4(corners, values, 0, x, y, z)...) + } + case Both: + { + tmp := mcToHex8(corners, values, 0, x, y, z) + if len(tmp) < 1 { + tmp = mcToTet4(corners, values, 0, x, y, z) } - case Quadratic: - { - switch shape { - case Hexahedral: - { - fes = append(fes, mcToHex20(corners, values, 0, x, y, z)...) - } - case Tetrahedral: - { - fes = append(fes, mcToTet10(corners, values, 0, x, y, z)...) - } - case Both: - { - tmp = mcToHex20(corners, values, 0, x, y, z) - if len(tmp) < 1 { - tmp = mcToTet10(corners, values, 0, x, y, z) - } - fes = append(fes, tmp...) - - } - } + fes = append(fes, tmp...) + } + } + } + case Quadratic: + { + switch shape { + case Hexahedral: + { + fes = append(fes, mcToHex20(corners, values, 0, x, y, z)...) + } + case Tetrahedral: + { + fes = append(fes, mcToTet10(corners, values, 0, x, y, z)...) + } + case Both: + { + tmp := mcToHex20(corners, values, 0, x, y, z) + if len(tmp) < 1 { + tmp = mcToTet10(corners, values, 0, x, y, z) } + fes = append(fes, tmp...) } - p.Y += dy } - p.X += dx } - p.Z += dz } return fes From fa7a15b50766d25e7ba0a631922df3fcdead2019 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 12:31:12 +0330 Subject: [PATCH 504/775] Delete constant parameter --- render/marchfelogic.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index ca3850e30..8b0649679 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -57,7 +57,7 @@ func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape l.Get(x+1, y+1, 1), l.Get(x, y+1, 1), } - fes = append(fes, mcToFE(corners, values, 0, x, y, z, order, shape)...) + fes = append(fes, mcToFE(corners, values, x, y, z, order, shape)...) p.Y += dy } p.X += dx @@ -70,7 +70,7 @@ func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape //----------------------------------------------------------------------------- -func mcToFE(corners [8]v3.Vec, values [8]float64, zero float64, x, y, z int, order Order, shape Shape) []*Fe { +func mcToFE(corners [8]v3.Vec, values [8]float64, x, y, z int, order Order, shape Shape) []*Fe { var fes []*Fe switch order { case Linear: From 0c2ab6cb78a7ffc29183e6d00a722fce65be3fd3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 12:32:19 +0330 Subject: [PATCH 505/775] Comment --- render/marchfelogic.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index 8b0649679..ef40fd2e7 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -135,9 +135,6 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) // Create a finite element if all 8 values are non-positive. // Finite element is inside the 3D model if all values are non-positive. - // Of course, some spaces are missed by this approach. - // - // TODO: Come up with a more sophisticated approach? if !anyPositive { fe := Fe{ @@ -179,9 +176,6 @@ func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) // Create a finite element if all 8 values are non-positive. // Finite element is inside the 3D model if all values are non-positive. - // Of course, some spaces are missed by this approach. - // - // TODO: Come up with a more sophisticated approach? if !anyPositive { fe := Fe{ From 3045909ff0908427a0601b9ac24ff176bea63059 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 12:45:21 +0330 Subject: [PATCH 506/775] Simplify --- render/marchfelogic.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index ef40fd2e7..72ae0c6b2 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -322,12 +322,12 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // Points on tetrahedron edges. // Followoing CalculiX node numbering. - t.V[5-1] = t.V[1-1].Add(t.V[2-1]).MulScalar(0.5) - t.V[6-1] = t.V[2-1].Add(t.V[3-1]).MulScalar(0.5) - t.V[7-1] = t.V[1-1].Add(t.V[3-1]).MulScalar(0.5) - t.V[8-1] = t.V[1-1].Add(t.V[4-1]).MulScalar(0.5) - t.V[9-1] = t.V[2-1].Add(t.V[4-1]).MulScalar(0.5) - t.V[10-1] = t.V[3-1].Add(t.V[4-1]).MulScalar(0.5) + t.V[4] = t.V[0].Add(t.V[1]).MulScalar(0.5) + t.V[5] = t.V[1].Add(t.V[2]).MulScalar(0.5) + t.V[6] = t.V[0].Add(t.V[2]).MulScalar(0.5) + t.V[7] = t.V[0].Add(t.V[3]).MulScalar(0.5) + t.V[8] = t.V[1].Add(t.V[3]).MulScalar(0.5) + t.V[9] = t.V[2].Add(t.V[3]).MulScalar(0.5) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) From 2cd6af1dd49479212c7d0bd242ddda406e4cb6f6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 12:53:40 +0330 Subject: [PATCH 507/775] Delete debug logs. Comment --- render/marchfelogic.go | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index 72ae0c6b2..bdd9b65b6 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -1,8 +1,6 @@ package render import ( - "fmt" - "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" @@ -259,20 +257,16 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) - flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) + flat, _ := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, jacobianDeterminant := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) + bad, _ := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) if !degenerated && !bad && !flat { result = append(result, &t) } else { - fmt.Println("Bad element: tet4") - fmt.Println("Non-positive Jacobian determinant? ", bad) - fmt.Println("Jacobian determinant: ", jacobianDeterminant) - fmt.Println("Almost flat? ", flat) - fmt.Println("Volume: ", volume) - fmt.Println("Degenerated? ", degenerated) + // CCX solver may throw error for this element. So, skip it. + // *ERROR in e_c3d: nonpositive jacobian determinant in element } } @@ -319,7 +313,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) - flat, volume := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) + flat, _ := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // Points on tetrahedron edges. // Followoing CalculiX node numbering. t.V[4] = t.V[0].Add(t.V[1]).MulScalar(0.5) @@ -330,16 +324,12 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) t.V[9] = t.V[2].Add(t.V[3]).MulScalar(0.5) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: - bad, jacobianDeterminant := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) + bad, _ := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) if !degenerated && !bad && !flat { result = append(result, &t) } else { - fmt.Println("Bad element: tet10") - fmt.Println("Non-positive Jacobian determinant? ", bad) - fmt.Println("Jacobian determinant: ", jacobianDeterminant) - fmt.Println("Almost flat? ", flat) - fmt.Println("Volume: ", volume) - fmt.Println("Degenerated? ", degenerated) + // CCX solver may throw error for this element. So, skip it. + // *ERROR in e_c3d: nonpositive jacobian determinant in element } } From 222276cdc7c42628aeac7ffee9fd1e7f459591b0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 17:26:11 +0330 Subject: [PATCH 508/775] Change input model --- examples/finite_elements/main.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c86f64454..e41788153 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -37,7 +37,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - stl := "../../files/teapot.stl" + stl := "../../files/hinge.stl" // read the stl file. file, err := os.OpenFile(stl, os.O_RDONLY, 0400) @@ -46,43 +46,43 @@ func main() { } // create the SDF from the STL mesh - teapotSdf, err := obj.ImportSTL(file, 20, 3, 5) + hingeSdf, err := obj.ImportSTL(file, 20, 3, 5) if err != nil { log.Fatalf("error: %s", err) } // tet4 i.e. 4-node tetrahedron - err = fe(teapotSdf, 80, render.Linear, render.Tetrahedral, "teapot-tet4.inp", 0, 20) + err = fe(hingeSdf, 80, render.Linear, render.Tetrahedral, "hinge-tet4.inp", 0, 10) if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fe(teapotSdf, 80, render.Quadratic, render.Tetrahedral, "teapot-tet10.inp", 0, 20) + err = fe(hingeSdf, 80, render.Quadratic, render.Tetrahedral, "hinge-tet10.inp", 0, 10) if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fe(teapotSdf, 80, render.Linear, render.Hexahedral, "teapot-hex8.inp", 0, 20) + err = fe(hingeSdf, 80, render.Linear, render.Hexahedral, "hinge-hex8.inp", 0, 10) if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fe(teapotSdf, 80, render.Quadratic, render.Hexahedral, "teapot-hex20.inp", 0, 20) + err = fe(hingeSdf, 80, render.Quadratic, render.Hexahedral, "hinge-hex20.inp", 0, 10) if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fe(teapotSdf, 80, render.Linear, render.Both, "teapot-hex8tet4.inp", 0, 20) + err = fe(hingeSdf, 80, render.Linear, render.Both, "hinge-hex8tet4.inp", 0, 10) if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fe(teapotSdf, 80, render.Quadratic, render.Both, "teapot-hex20tet10.inp", 0, 20) + err = fe(hingeSdf, 80, render.Quadratic, render.Both, "hinge-hex20tet10.inp", 0, 10) if err != nil { log.Fatalf("error: %s", err) } From bb864fbe09197fb8c297eb50d7b525e218ea24d0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 14 Jun 2023 17:26:24 +0330 Subject: [PATCH 509/775] Revert "Change input model" This reverts commit 222276cdc7c42628aeac7ffee9fd1e7f459591b0. --- examples/finite_elements/main.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index e41788153..c86f64454 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -37,7 +37,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - stl := "../../files/hinge.stl" + stl := "../../files/teapot.stl" // read the stl file. file, err := os.OpenFile(stl, os.O_RDONLY, 0400) @@ -46,43 +46,43 @@ func main() { } // create the SDF from the STL mesh - hingeSdf, err := obj.ImportSTL(file, 20, 3, 5) + teapotSdf, err := obj.ImportSTL(file, 20, 3, 5) if err != nil { log.Fatalf("error: %s", err) } // tet4 i.e. 4-node tetrahedron - err = fe(hingeSdf, 80, render.Linear, render.Tetrahedral, "hinge-tet4.inp", 0, 10) + err = fe(teapotSdf, 80, render.Linear, render.Tetrahedral, "teapot-tet4.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fe(hingeSdf, 80, render.Quadratic, render.Tetrahedral, "hinge-tet10.inp", 0, 10) + err = fe(teapotSdf, 80, render.Quadratic, render.Tetrahedral, "teapot-tet10.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fe(hingeSdf, 80, render.Linear, render.Hexahedral, "hinge-hex8.inp", 0, 10) + err = fe(teapotSdf, 80, render.Linear, render.Hexahedral, "teapot-hex8.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fe(hingeSdf, 80, render.Quadratic, render.Hexahedral, "hinge-hex20.inp", 0, 10) + err = fe(teapotSdf, 80, render.Quadratic, render.Hexahedral, "teapot-hex20.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fe(hingeSdf, 80, render.Linear, render.Both, "hinge-hex8tet4.inp", 0, 10) + err = fe(teapotSdf, 80, render.Linear, render.Both, "teapot-hex8tet4.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fe(hingeSdf, 80, render.Quadratic, render.Both, "hinge-hex20tet10.inp", 0, 10) + err = fe(teapotSdf, 80, render.Quadratic, render.Both, "teapot-hex20tet10.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } From 9b2bab5fd19bf74478c8c54f65c3b84854557c80 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 15 Jun 2023 11:23:37 +0330 Subject: [PATCH 510/775] Comment --- render/marchfelogic.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index bdd9b65b6..805f7d20e 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -84,6 +84,9 @@ func mcToFE(corners [8]v3.Vec, values [8]float64, x, y, z int, order Order, shap } case Both: { + // If all cube corners are inside surface mesh, a single hexahedral element is generated. + // If all cube corners are outside surface mesh, no element is generated. + // If cube is colliding with surface mesh, one or more tetrahedral elements are generated. tmp := mcToHex8(corners, values, 0, x, y, z) if len(tmp) < 1 { tmp = mcToTet4(corners, values, 0, x, y, z) @@ -105,6 +108,9 @@ func mcToFE(corners [8]v3.Vec, values [8]float64, x, y, z int, order Order, shap } case Both: { + // If all cube corners are inside surface mesh, a single hexahedral element is generated. + // If all cube corners are outside surface mesh, no element is generated. + // If cube is colliding with surface mesh, one or more tetrahedral elements are generated. tmp := mcToHex20(corners, values, 0, x, y, z) if len(tmp) < 1 { tmp = mcToTet10(corners, values, 0, x, y, z) From 0ba4d170df1f85cc831f6f87d2e7ce5353d277e5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 15 Jun 2023 13:20:07 +0330 Subject: [PATCH 511/775] Comment --- render/marchfe.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/marchfe.go b/render/marchfe.go index 5253902ba..b43fa3df8 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -33,8 +33,8 @@ const ( // MarchingCubesFEUniform renders using marching cubes with uniform space sampling. type MarchingCubesFEUniform struct { meshCells int // number of cells on the longest axis of bounding box. e.g 200 - order Order // - shape Shape // + order Order // Linear or quadratic. + shape Shape // Hexahedral, tetrahedral, or both. } // NewMarchingCubesFEUniform returns a RenderHex8 object. From e337c530f95f9a1326b2861c577729292ee794e6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 15 Jun 2023 13:39:54 +0330 Subject: [PATCH 512/775] Linux exe with Intel Pardiso Solver --- examples/finite_elements/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 05449c95f..20bcaa3bc 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -50,3 +50,9 @@ cgx teapot-hex8.frd teapot-hex8.inp ## Math solver The default CCX math solver is `SPOOLES` which is slow. Apparently `PARDISO` is faster and `PaStiX` is the fastest. But it's needed to build the CCX with `PARDISO` or `PaStiX` math libraries. + +### PARDISO + +#### Linux executable with the Intel Pardiso Solver + +You can download [here](https://www.dropbox.com/s/x8axi53l9dk9w4g/ccx_2.19_MT?dl=1) an executable with the Intel Pardiso solver for x86_64 Linux systems. The executable has all the libraries statically linked into it. So it should run by itself without any dependency. Thanks to [these guys](https://www.feacluster.com/calculix.php). From b06c3ef7c304e729f0cc3129572ac3db41971365 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 17 Jun 2023 15:31:12 +0330 Subject: [PATCH 513/775] Dilate input SDF to get rid of bad elements: ... like disconnected or improperly connected elements. --- examples/finite_elements/main.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c86f64454..345d85ece 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -11,6 +11,7 @@ package main import ( "log" + "math" "os" "github.com/deadsy/sdfx/obj" @@ -21,11 +22,22 @@ import ( // Generate finite elements. func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, layerStart, layerEnd int) error { + min := s.BoundingBox().Min + max := s.BoundingBox().Max + + kX := (max.X - min.X) / float64(100) + kY := (max.Y - min.Y) / float64(100) + kZ := (max.Z - min.Z) / float64(100) + + // By dilating SDF a little bit we may actually get rid of bad elements like disconnected or improperly connected elements. + dilation := sdf.Offset3D(s, math.Min(kX, math.Min(kY, kZ))) + // Create a mesh out of finite elements. - m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) + m, _ := mesh.NewFem(dilation, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to a file. err := m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + //err := m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3) if err != nil { return err } From 5393d131a43a1b4da91d1f6d7a5e799984465c57 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 17 Jun 2023 15:36:39 +0330 Subject: [PATCH 514/775] Comment --- render/marchfehelper.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/render/marchfehelper.go b/render/marchfehelper.go index 2948f7c52..e3885f937 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -308,6 +308,8 @@ func isBadGaussTet10(coords [10]v3.Vec, xi, et, ze float64) (bool, float64) { //----------------------------------------------------------------------------- +// Exactly follow CCX source code leading to this error: +// *ERROR in e_c3d: nonpositive jacobian determinant in element func isBadTet4(coords [4]v3.Vec) (bool, float64) { // xi, et, and ze are the coordinates of the Gauss point @@ -324,6 +326,8 @@ func isBadTet4(coords [4]v3.Vec) (bool, float64) { return isBadGaussTet4(coords, xi, et, ze) } +// Exactly follow CCX source code leading to this error: +// *ERROR in e_c3d: nonpositive jacobian determinant in element func isBadTet10(coords [10]v3.Vec) (bool, float64) { // Gause points are according to CCX source code. // Reference: From bfdc5e69da004c05fb0ed08150274f674dc436c8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 17 Jun 2023 15:38:40 +0330 Subject: [PATCH 515/775] Comment --- render/marchfehelper.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/render/marchfehelper.go b/render/marchfehelper.go index e3885f937..ad793bd73 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -208,11 +208,7 @@ func isBadGaussTet4(coords [4]v3.Vec, xi, et, ze float64) (bool, float64) { xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) // According to CCX source code to detect nonpositive jacobian determinant in element - // // Fortran threshold for non-positive Jacobian determinant is 1e-20. - // But, for example a bad element with non-positive Jacobian determinant - // of 0.0025717779019105687 is escaping the 1e-20 threshold. - // Seems like we need to make the threshold safer. return xsj < 1e-20, xsj } @@ -298,11 +294,7 @@ func isBadGaussTet10(coords [10]v3.Vec, xi, et, ze float64) (bool, float64) { xs[0][2]*(xs[1][0]*xs[2][1]-xs[1][1]*xs[2][0]) // According to CCX source code to detect nonpositive jacobian determinant in element - // // Fortran threshold for non-positive Jacobian determinant is 1e-20. - // But, for example a bad element with non-positive Jacobian determinant - // of 0.0025717779019105687 is escaping the 1e-20 threshold. - // Seems like we need to make the threshold safer. return xsj < 1e-20, xsj } From d40d3cd3886b8b2e02747197e99a0f5ba7c65a0a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 17 Jun 2023 15:39:32 +0330 Subject: [PATCH 516/775] Skip check: almost flat tetrahedron --- render/marchfelogic.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index 805f7d20e..bd05d506e 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -263,12 +263,11 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) - flat, _ := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, _ := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) - if !degenerated && !bad && !flat { + if !degenerated && !bad { result = append(result, &t) } else { // CCX solver may throw error for this element. So, skip it. @@ -319,7 +318,6 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) - flat, _ := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // Points on tetrahedron edges. // Followoing CalculiX node numbering. t.V[4] = t.V[0].Add(t.V[1]).MulScalar(0.5) @@ -331,7 +329,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, _ := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) - if !degenerated && !bad && !flat { + if !degenerated && !bad { result = append(result, &t) } else { // CCX solver may throw error for this element. So, skip it. From 0fa740110d24b51c78c8da6a32fe11ac548bd2e5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 17 Jun 2023 15:41:54 +0330 Subject: [PATCH 517/775] Revert "Skip check: almost flat tetrahedron" This reverts commit d40d3cd3886b8b2e02747197e99a0f5ba7c65a0a. --- render/marchfelogic.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index bd05d506e..805f7d20e 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -263,11 +263,12 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) + flat, _ := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, _ := isBadTet4([4]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3]}) - if !degenerated && !bad { + if !degenerated && !bad && !flat { result = append(result, &t) } else { // CCX solver may throw error for this element. So, skip it. @@ -318,6 +319,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) t.V[2] = point(points, p, table[i*4+2]) t.V[3] = point(points, p, table[i*4+3]) degenerated := degenerateTriangles(t.V[0], t.V[1], t.V[2], t.V[3]) + flat, _ := almostFlat(t.V[0], t.V[1], t.V[2], t.V[3]) // Points on tetrahedron edges. // Followoing CalculiX node numbering. t.V[4] = t.V[0].Add(t.V[1]).MulScalar(0.5) @@ -329,7 +331,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) // In the case of marching cubes algorithm to generate triangle, it's avoiding zero-area triangles by `!t.Degenerate(0)` check. // In our case of marching cubes algorithm to generate tetrahedron, we can do a check too: bad, _ := isBadTet10([10]v3.Vec{t.V[0], t.V[1], t.V[2], t.V[3], t.V[4], t.V[5], t.V[6], t.V[7], t.V[8], t.V[9]}) - if !degenerated && !bad { + if !degenerated && !bad && !flat { result = append(result, &t) } else { // CCX solver may throw error for this element. So, skip it. From b0dbcb897f9c10eadf5e704e92b11d437020f810 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 17 Jun 2023 15:44:26 +0330 Subject: [PATCH 518/775] Calibrate almost-flat tolerance --- render/marchfehelper.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/render/marchfehelper.go b/render/marchfehelper.go index ad793bd73..141933bfe 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -138,9 +138,10 @@ func almostFlat(a, b, c, d v3.Vec) (bool, float64) { volume := 1.0 / 6.0 * math.Abs(ab.Cross(ac).Dot(ad)) denom := (nab + ncd) * (nac + nbd) * (nad + nbc) - // Tolerance derived from here: + // Tolerance derived from here would be `480.0`: // https://math.stackexchange.com/a/4709610/197913 - tolerance := 480.0 + // We choose a different value according to observations. + tolerance := 1000.0 rho := tolerance * volume / denom From 127cd86028451b6c1e847568859971b3f4e39156 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 17 Jun 2023 16:31:02 +0330 Subject: [PATCH 519/775] Comment --- render/marchfehelper.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/render/marchfehelper.go b/render/marchfehelper.go index 141933bfe..eecd8cf1f 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -140,7 +140,8 @@ func almostFlat(a, b, c, d v3.Vec) (bool, float64) { // Tolerance derived from here would be `480.0`: // https://math.stackexchange.com/a/4709610/197913 - // We choose a different value according to observations. + // A different value is calibrated according to observations. + // TODO: Could be further calibrated. tolerance := 1000.0 rho := tolerance * volume / denom From b39956d64e61f0b061cdd78a1b3a13f943ea94ab Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 18 Jun 2023 02:18:04 -0700 Subject: [PATCH 520/775] Dilation factor --- examples/finite_elements/main.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 345d85ece..9f9c3f57c 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -25,9 +25,10 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth min := s.BoundingBox().Min max := s.BoundingBox().Max - kX := (max.X - min.X) / float64(100) - kY := (max.Y - min.Y) / float64(100) - kZ := (max.Z - min.Z) / float64(100) + dilationFactor := float64(0.02) + kX := (max.X - min.X) * dilationFactor + kY := (max.Y - min.Y) * dilationFactor + kZ := (max.Z - min.Z) * dilationFactor // By dilating SDF a little bit we may actually get rid of bad elements like disconnected or improperly connected elements. dilation := sdf.Offset3D(s, math.Min(kX, math.Min(kY, kZ))) From f6b3738e95c0fecc4f503bcc751bd83e68a094a6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 18 Jun 2023 03:40:42 -0700 Subject: [PATCH 521/775] SDF erosion after dilation --- examples/finite_elements/main.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 9f9c3f57c..c7e2f0554 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -25,16 +25,18 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth min := s.BoundingBox().Min max := s.BoundingBox().Max - dilationFactor := float64(0.02) - kX := (max.X - min.X) * dilationFactor - kY := (max.Y - min.Y) * dilationFactor - kZ := (max.Z - min.Z) * dilationFactor + dimX := (max.X - min.X) + dimY := (max.Y - min.Y) + dimZ := (max.Z - min.Z) + factor := math.Min(dimX, math.Min(dimY, dimZ)) * float64(0.02) // By dilating SDF a little bit we may actually get rid of bad elements like disconnected or improperly connected elements. - dilation := sdf.Offset3D(s, math.Min(kX, math.Min(kY, kZ))) + dilation := sdf.Offset3D(s, factor) + + erosion := sdf.Offset3D(dilation, -factor) // Create a mesh out of finite elements. - m, _ := mesh.NewFem(dilation, render.NewMarchingCubesFEUniform(resolution, order, shape)) + m, _ := mesh.NewFem(erosion, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to a file. err := m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) From 1ae227a05cb5ebd25528fdcca177b1ab37785d67 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 18 Jun 2023 08:15:38 -0700 Subject: [PATCH 522/775] Change dilation + erosion factor. Comment. --- examples/finite_elements/main.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c7e2f0554..5ec3aeab0 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -28,19 +28,20 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth dimX := (max.X - min.X) dimY := (max.Y - min.Y) dimZ := (max.Z - min.Z) - factor := math.Min(dimX, math.Min(dimY, dimZ)) * float64(0.02) + factor := math.Min(dimX, math.Min(dimY, dimZ)) * float64(0.05) // By dilating SDF a little bit we may actually get rid of bad elements like disconnected or improperly connected elements. dilation := sdf.Offset3D(s, factor) + // Erode so that SDF returns to its original size, well almost. erosion := sdf.Offset3D(dilation, -factor) // Create a mesh out of finite elements. m, _ := mesh.NewFem(erosion, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to a file. - err := m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) - //err := m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + //err := m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + err := m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3) if err != nil { return err } From 23b67ab4f6719cf44967f578f8e198aac3e3d808 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 18 Jun 2023 08:36:16 -0700 Subject: [PATCH 523/775] Code review hint --- examples/finite_elements/main.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 5ec3aeab0..b8228923b 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -40,13 +40,9 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth m, _ := mesh.NewFem(erosion, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to a file. - //err := m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) - err := m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3) - if err != nil { - return err - } + //return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) - return nil + return m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3) } // Render SDF3 to finite elements. From 11e4abd1f7aa120878fc0a311832918a2e9ec92b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 19 Jun 2023 02:44:00 -0700 Subject: [PATCH 524/775] Reduce resolution, according to FEA community: > ... STL (and other CAD) models often contain lots of small details that are irrelevant for the analysis, but force the use of lots of small elements. > ... to generate the geometry and mesh (omitting small and inconsequential details) in my experience tends to produce a higher quality mesh ... --- examples/finite_elements/main.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index b8228923b..88be9f776 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -64,37 +64,37 @@ func main() { } // tet4 i.e. 4-node tetrahedron - err = fe(teapotSdf, 80, render.Linear, render.Tetrahedral, "teapot-tet4.inp", 0, 20) + err = fe(teapotSdf, 50, render.Linear, render.Tetrahedral, "teapot-tet4.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fe(teapotSdf, 80, render.Quadratic, render.Tetrahedral, "teapot-tet10.inp", 0, 20) + err = fe(teapotSdf, 50, render.Quadratic, render.Tetrahedral, "teapot-tet10.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fe(teapotSdf, 80, render.Linear, render.Hexahedral, "teapot-hex8.inp", 0, 20) + err = fe(teapotSdf, 50, render.Linear, render.Hexahedral, "teapot-hex8.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fe(teapotSdf, 80, render.Quadratic, render.Hexahedral, "teapot-hex20.inp", 0, 20) + err = fe(teapotSdf, 50, render.Quadratic, render.Hexahedral, "teapot-hex20.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fe(teapotSdf, 80, render.Linear, render.Both, "teapot-hex8tet4.inp", 0, 20) + err = fe(teapotSdf, 50, render.Linear, render.Both, "teapot-hex8tet4.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fe(teapotSdf, 80, render.Quadratic, render.Both, "teapot-hex20tet10.inp", 0, 20) + err = fe(teapotSdf, 50, render.Quadratic, render.Both, "teapot-hex20tet10.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } From 2d6ce0fae68bfb6aceca0bb97359bf64f1547fd0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 19 Jun 2023 05:03:26 -0700 Subject: [PATCH 525/775] Cleanup and separate methods --- examples/finite_elements/main.go | 87 ++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 16 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 88be9f776..bdf35851e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -20,31 +20,50 @@ import ( "github.com/deadsy/sdfx/sdf" ) -// Generate finite elements. -func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, layerStart, layerEnd int) error { +// By dilating SDF a little bit we may actually get rid of +// bad elements like disconnected or improperly connected elements. +// Erode so that SDF returns to its original size, well almost. +func dilationErosion(s sdf.SDF3) sdf.SDF3 { min := s.BoundingBox().Min max := s.BoundingBox().Max dimX := (max.X - min.X) dimY := (max.Y - min.Y) dimZ := (max.Z - min.Z) - factor := math.Min(dimX, math.Min(dimY, dimZ)) * float64(0.05) - // By dilating SDF a little bit we may actually get rid of bad elements like disconnected or improperly connected elements. - dilation := sdf.Offset3D(s, factor) + // What percent is preferred? Calibration is done a bit. + factor := math.Min(dimX, math.Min(dimY, dimZ)) * float64(0.02) - // Erode so that SDF returns to its original size, well almost. + dilation := sdf.Offset3D(s, factor) erosion := sdf.Offset3D(dilation, -factor) - // Create a mesh out of finite elements. - m, _ := mesh.NewFem(erosion, render.NewMarchingCubesFEUniform(resolution, order, shape)) + return erosion +} - // Write just some layers of mesh to a file. - //return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) +// Generate finite elements. +func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string) error { + s = dilationErosion(s) + // Create a mesh out of finite elements. + m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) + + // Write all layers of mesh to file. return m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3) } +// Generate finite elements. +// Only from a start layer to an end layer along the Z axis. +// Applicable to 3D print analysis that is done layer-by-layer. +func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, layerStart, layerEnd int) error { + s = dilationErosion(s) + + // Create a mesh out of finite elements. + m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) + + // Write just some layers of mesh to file. + return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) +} + // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. @@ -64,37 +83,73 @@ func main() { } // tet4 i.e. 4-node tetrahedron - err = fe(teapotSdf, 50, render.Linear, render.Tetrahedral, "teapot-tet4.inp", 0, 20) + err = fe(teapotSdf, 50, render.Linear, render.Tetrahedral, "teapot-tet4.inp") + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet4 i.e. 4-node tetrahedron + err = fePartial(teapotSdf, 50, render.Linear, render.Tetrahedral, "teapot-partial-tet4.inp", 0, 20) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet10 i.e. 10-node tetrahedron + err = fe(teapotSdf, 50, render.Quadratic, render.Tetrahedral, "teapot-tet10.inp") if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fe(teapotSdf, 50, render.Quadratic, render.Tetrahedral, "teapot-tet10.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Quadratic, render.Tetrahedral, "teapot-partial-tet10.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fe(teapotSdf, 50, render.Linear, render.Hexahedral, "teapot-hex8.inp", 0, 20) + err = fe(teapotSdf, 50, render.Linear, render.Hexahedral, "teapot-hex8.inp") + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 i.e. 8-node hexahedron + err = fePartial(teapotSdf, 50, render.Linear, render.Hexahedral, "teapot-partial-hex8.inp", 0, 20) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 i.e. 20-node hexahedron + err = fe(teapotSdf, 50, render.Quadratic, render.Hexahedral, "teapot-hex20.inp") if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fe(teapotSdf, 50, render.Quadratic, render.Hexahedral, "teapot-hex20.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Quadratic, render.Hexahedral, "teapot-partial-hex20.inp", 0, 20) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 and tet4 + err = fe(teapotSdf, 50, render.Linear, render.Both, "teapot-hex8tet4.inp") if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fe(teapotSdf, 50, render.Linear, render.Both, "teapot-hex8tet4.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Linear, render.Both, "teapot-partial-hex8tet4.inp", 0, 20) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 and tet10 + err = fe(teapotSdf, 50, render.Quadratic, render.Both, "teapot-hex20tet10.inp") if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fe(teapotSdf, 50, render.Quadratic, render.Both, "teapot-hex20tet10.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Quadratic, render.Both, "teapot-partial-hex20tet10.inp", 0, 20) if err != nil { log.Fatalf("error: %s", err) } From b7973b8bbda55e5671ceef8c631a4efcb7796b31 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 19 Jun 2023 16:46:47 +0330 Subject: [PATCH 526/775] Set layer when artifact begins --- examples/finite_elements/main.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index bdf35851e..2655bf76e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -89,7 +89,7 @@ func main() { } // tet4 i.e. 4-node tetrahedron - err = fePartial(teapotSdf, 50, render.Linear, render.Tetrahedral, "teapot-partial-tet4.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Linear, render.Tetrahedral, "teapot-partial-tet4.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -101,7 +101,7 @@ func main() { } // tet10 i.e. 10-node tetrahedron - err = fePartial(teapotSdf, 50, render.Quadratic, render.Tetrahedral, "teapot-partial-tet10.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Quadratic, render.Tetrahedral, "teapot-partial-tet10.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -113,7 +113,7 @@ func main() { } // hex8 i.e. 8-node hexahedron - err = fePartial(teapotSdf, 50, render.Linear, render.Hexahedral, "teapot-partial-hex8.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Linear, render.Hexahedral, "teapot-partial-hex8.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -125,7 +125,7 @@ func main() { } // hex20 i.e. 20-node hexahedron - err = fePartial(teapotSdf, 50, render.Quadratic, render.Hexahedral, "teapot-partial-hex20.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Quadratic, render.Hexahedral, "teapot-partial-hex20.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -137,7 +137,7 @@ func main() { } // hex8 and tet4 - err = fePartial(teapotSdf, 50, render.Linear, render.Both, "teapot-partial-hex8tet4.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Linear, render.Both, "teapot-partial-hex8tet4.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -149,7 +149,7 @@ func main() { } // hex20 and tet10 - err = fePartial(teapotSdf, 50, render.Quadratic, render.Both, "teapot-partial-hex20tet10.inp", 0, 20) + err = fePartial(teapotSdf, 50, render.Quadratic, render.Both, "teapot-partial-hex20tet10.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } From 9a74bca4b03f6e727cd0f1e369477f63833b844b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 22 Jun 2023 10:35:33 +0330 Subject: [PATCH 527/775] Update read-me --- examples/finite_elements/README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 20bcaa3bc..92f8cdf4d 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -1,6 +1,24 @@ +# Output + +## Nodes and elements + +Output is generated as `inp` files for ABAQUS or CalculiX. Nodes and elements are saved in separate files, which are then included inside a single, final `inp` file. This final `inp` file can be opened and viewed using [FreeCAD](https://en.wikipedia.org/wiki/FreeCAD). + +## Loading + +The final `inp` file applies a distributed *weight* load to all elements. This load is calculated according to the material density. This load is in `+Z` direction. Assuming the 3D model will be 3D printed upside-down by SLA technology. + +## Boundary + +In the final `inp` file, the boundary is defined by the first few layers at the bottom of the 3D model. Assuming the 3D model will be 3D printed upside-down by SLA technology. + +## Modification + +Currently, no convenient ways are provided here for adjusting loading and boundary conditions. However, they may be developed and offered in the future. + # CCX and CGX -The example results can be consumed by ABAQUS or CalculiX. +The results can be consumed by ABAQUS or CalculiX. CalculiX and CalculiX GraphiX binaries are available for different platforms, like Linux distributions. From 1c11d1b83f5e0aaeeb9ff240902fcd98f9dd849c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 24 Jun 2023 12:21:35 +0330 Subject: [PATCH 528/775] Test: `hinge` STL of WELSIM software --- examples/finite_elements/main.go | 28 +- files/hinge.stl | 8486 ++++++++++++++++++++++++++++++ 2 files changed, 8500 insertions(+), 14 deletions(-) create mode 100644 files/hinge.stl diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 2655bf76e..c9e14a91c 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -68,7 +68,7 @@ func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shap // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - stl := "../../files/teapot.stl" + stl := "../../files/hinge.stl" // read the stl file. file, err := os.OpenFile(stl, os.O_RDONLY, 0400) @@ -77,79 +77,79 @@ func main() { } // create the SDF from the STL mesh - teapotSdf, err := obj.ImportSTL(file, 20, 3, 5) + hingeSdf, err := obj.ImportSTL(file, 20, 3, 5) if err != nil { log.Fatalf("error: %s", err) } // tet4 i.e. 4-node tetrahedron - err = fe(teapotSdf, 50, render.Linear, render.Tetrahedral, "teapot-tet4.inp") + err = fe(hingeSdf, 50, render.Linear, render.Tetrahedral, "hinge-tet4.inp") if err != nil { log.Fatalf("error: %s", err) } // tet4 i.e. 4-node tetrahedron - err = fePartial(teapotSdf, 50, render.Linear, render.Tetrahedral, "teapot-partial-tet4.inp", 0, 15) + err = fePartial(hingeSdf, 50, render.Linear, render.Tetrahedral, "hinge-partial-tet4.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fe(teapotSdf, 50, render.Quadratic, render.Tetrahedral, "teapot-tet10.inp") + err = fe(hingeSdf, 50, render.Quadratic, render.Tetrahedral, "hinge-tet10.inp") if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fePartial(teapotSdf, 50, render.Quadratic, render.Tetrahedral, "teapot-partial-tet10.inp", 0, 15) + err = fePartial(hingeSdf, 50, render.Quadratic, render.Tetrahedral, "hinge-partial-tet10.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fe(teapotSdf, 50, render.Linear, render.Hexahedral, "teapot-hex8.inp") + err = fe(hingeSdf, 50, render.Linear, render.Hexahedral, "hinge-hex8.inp") if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fePartial(teapotSdf, 50, render.Linear, render.Hexahedral, "teapot-partial-hex8.inp", 0, 15) + err = fePartial(hingeSdf, 50, render.Linear, render.Hexahedral, "hinge-partial-hex8.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fe(teapotSdf, 50, render.Quadratic, render.Hexahedral, "teapot-hex20.inp") + err = fe(hingeSdf, 50, render.Quadratic, render.Hexahedral, "hinge-hex20.inp") if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fePartial(teapotSdf, 50, render.Quadratic, render.Hexahedral, "teapot-partial-hex20.inp", 0, 15) + err = fePartial(hingeSdf, 50, render.Quadratic, render.Hexahedral, "hinge-partial-hex20.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fe(teapotSdf, 50, render.Linear, render.Both, "teapot-hex8tet4.inp") + err = fe(hingeSdf, 50, render.Linear, render.Both, "hinge-hex8tet4.inp") if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fePartial(teapotSdf, 50, render.Linear, render.Both, "teapot-partial-hex8tet4.inp", 0, 15) + err = fePartial(hingeSdf, 50, render.Linear, render.Both, "hinge-partial-hex8tet4.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fe(teapotSdf, 50, render.Quadratic, render.Both, "teapot-hex20tet10.inp") + err = fe(hingeSdf, 50, render.Quadratic, render.Both, "hinge-hex20tet10.inp") if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fePartial(teapotSdf, 50, render.Quadratic, render.Both, "teapot-partial-hex20tet10.inp", 0, 15) + err = fePartial(hingeSdf, 50, render.Quadratic, render.Both, "hinge-partial-hex20tet10.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } diff --git a/files/hinge.stl b/files/hinge.stl new file mode 100644 index 000000000..acb421d45 --- /dev/null +++ b/files/hinge.stl @@ -0,0 +1,8486 @@ +solid + facet normal 5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 3.832020e+001 1.706140e+001 5.000000e+000 + vertex 3.837337e+001 1.645363e+001 5.000000e+000 + vertex 3.932020e+001 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 3.935818e+001 1.749552e+001 4.399139e+000 + vertex 3.832020e+001 1.706140e+001 5.000000e+000 + vertex 3.932020e+001 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 3.935818e+001 1.749552e+001 4.399139e+000 + vertex 3.837337e+001 1.766917e+001 5.000000e+000 + vertex 3.832020e+001 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 3.935818e+001 1.749552e+001 4.399139e+000 + vertex 3.853128e+001 1.825847e+001 5.000000e+000 + vertex 3.837337e+001 1.766917e+001 5.000000e+000 + endloop + endfacet + facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 3.935818e+001 1.749552e+001 4.399139e+000 + vertex 3.947097e+001 1.791645e+001 4.399139e+000 + vertex 3.853128e+001 1.825847e+001 5.000000e+000 + endloop + endfacet + facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 3.853128e+001 1.825847e+001 5.000000e+000 + vertex 3.947097e+001 1.791645e+001 4.399139e+000 + vertex 3.878911e+001 1.881140e+001 5.000000e+000 + endloop + endfacet + facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 3.878911e+001 1.881140e+001 5.000000e+000 + vertex 3.947097e+001 1.791645e+001 4.399139e+000 + vertex 3.965514e+001 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 3.913904e+001 1.931116e+001 5.000000e+000 + vertex 3.965514e+001 1.831140e+001 4.399139e+000 + vertex 3.990509e+001 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 4.021323e+001 1.897651e+001 4.399139e+000 + vertex 3.913904e+001 1.931116e+001 5.000000e+000 + vertex 3.990509e+001 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 4.021323e+001 1.897651e+001 4.399139e+000 + vertex 3.957044e+001 1.974256e+001 5.000000e+000 + vertex 3.913904e+001 1.931116e+001 5.000000e+000 + endloop + endfacet + facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 4.021323e+001 1.897651e+001 4.399139e+000 + vertex 4.057020e+001 1.922646e+001 4.399139e+000 + vertex 3.957044e+001 1.974256e+001 5.000000e+000 + endloop + endfacet + facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 3.957044e+001 1.974256e+001 5.000000e+000 + vertex 4.057020e+001 1.922646e+001 4.399139e+000 + vertex 4.007020e+001 2.009249e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 4.007020e+001 2.009249e+001 5.000000e+000 + vertex 4.057020e+001 1.922646e+001 4.399139e+000 + vertex 4.062313e+001 2.035032e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 4.062313e+001 2.035032e+001 5.000000e+000 + vertex 4.057020e+001 1.922646e+001 4.399139e+000 + vertex 4.096515e+001 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 4.121243e+001 2.050823e+001 5.000000e+000 + vertex 4.096515e+001 1.941063e+001 4.399139e+000 + vertex 4.138608e+001 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 4.182020e+001 1.956140e+001 4.399139e+000 + vertex 4.121243e+001 2.050823e+001 5.000000e+000 + vertex 4.138608e+001 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 4.182020e+001 1.956140e+001 4.399139e+000 + vertex 4.182020e+001 2.056140e+001 5.000000e+000 + vertex 4.121243e+001 2.050823e+001 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 4.182020e+001 1.956140e+001 4.399139e+000 + vertex 4.225432e+001 1.952342e+001 4.399139e+000 + vertex 4.182020e+001 2.056140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 4.182020e+001 2.056140e+001 5.000000e+000 + vertex 4.225432e+001 1.952342e+001 4.399139e+000 + vertex 4.242797e+001 2.050823e+001 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 4.242797e+001 2.050823e+001 5.000000e+000 + vertex 4.225432e+001 1.952342e+001 4.399139e+000 + vertex 4.267525e+001 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 4.301727e+001 2.035032e+001 5.000000e+000 + vertex 4.267525e+001 1.941063e+001 4.399139e+000 + vertex 4.307020e+001 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 4.357020e+001 2.009249e+001 5.000000e+000 + vertex 4.307020e+001 1.922646e+001 4.399139e+000 + vertex 4.342717e+001 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 4.406996e+001 1.974256e+001 5.000000e+000 + vertex 4.342717e+001 1.897651e+001 4.399139e+000 + vertex 4.373531e+001 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 4.450136e+001 1.931116e+001 5.000000e+000 + vertex 4.373531e+001 1.866837e+001 4.399139e+000 + vertex 4.398526e+001 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 4.485129e+001 1.881140e+001 5.000000e+000 + vertex 4.398526e+001 1.831140e+001 4.399139e+000 + vertex 4.510912e+001 1.825847e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 4.485129e+001 1.881140e+001 5.000000e+000 + vertex 4.450136e+001 1.931116e+001 5.000000e+000 + vertex 4.398526e+001 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 3.837337e+001 1.645363e+001 5.000000e+000 + vertex 3.853128e+001 1.586433e+001 5.000000e+000 + vertex 3.947097e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal 4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 3.935818e+001 1.662728e+001 4.399139e+000 + vertex 3.837337e+001 1.645363e+001 5.000000e+000 + vertex 3.947097e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal 5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 3.935818e+001 1.662728e+001 4.399139e+000 + vertex 3.932020e+001 1.706140e+001 4.399139e+000 + vertex 3.837337e+001 1.645363e+001 5.000000e+000 + endloop + endfacet + facet normal 4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 3.853128e+001 1.586433e+001 5.000000e+000 + vertex 3.878911e+001 1.531140e+001 5.000000e+000 + vertex 3.965514e+001 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 3.947097e+001 1.620635e+001 4.399139e+000 + vertex 3.853128e+001 1.586433e+001 5.000000e+000 + vertex 3.965514e+001 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 3.878911e+001 1.531140e+001 5.000000e+000 + vertex 3.913904e+001 1.481164e+001 5.000000e+000 + vertex 3.990509e+001 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 3.965514e+001 1.581140e+001 4.399139e+000 + vertex 3.878911e+001 1.531140e+001 5.000000e+000 + vertex 3.990509e+001 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal 3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 3.913904e+001 1.481164e+001 5.000000e+000 + vertex 3.957044e+001 1.438024e+001 5.000000e+000 + vertex 3.990509e+001 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal 3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 3.990509e+001 1.545443e+001 4.399139e+000 + vertex 3.957044e+001 1.438024e+001 5.000000e+000 + vertex 4.021323e+001 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal 2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 4.021323e+001 1.514629e+001 4.399139e+000 + vertex 3.957044e+001 1.438024e+001 5.000000e+000 + vertex 4.057020e+001 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal 2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 4.057020e+001 1.489634e+001 4.399139e+000 + vertex 3.957044e+001 1.438024e+001 5.000000e+000 + vertex 4.007020e+001 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 4.062313e+001 1.377248e+001 5.000000e+000 + vertex 4.057020e+001 1.489634e+001 4.399139e+000 + vertex 4.007020e+001 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 4.062313e+001 1.377248e+001 5.000000e+000 + vertex 4.096515e+001 1.471217e+001 4.399139e+000 + vertex 4.057020e+001 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal 1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 4.062313e+001 1.377248e+001 5.000000e+000 + vertex 4.121243e+001 1.361457e+001 5.000000e+000 + vertex 4.096515e+001 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal 1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 4.096515e+001 1.471217e+001 4.399139e+000 + vertex 4.121243e+001 1.361457e+001 5.000000e+000 + vertex 4.138608e+001 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 4.138608e+001 1.459938e+001 4.399139e+000 + vertex 4.121243e+001 1.361457e+001 5.000000e+000 + vertex 4.182020e+001 1.456140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 4.182020e+001 1.456140e+001 4.399139e+000 + vertex 4.121243e+001 1.361457e+001 5.000000e+000 + vertex 4.182020e+001 1.356140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 4.225432e+001 1.459938e+001 4.399139e+000 + vertex 4.182020e+001 1.356140e+001 5.000000e+000 + vertex 4.242797e+001 1.361457e+001 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 4.267525e+001 1.471217e+001 4.399139e+000 + vertex 4.242797e+001 1.361457e+001 5.000000e+000 + vertex 4.301727e+001 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal -2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 4.357020e+001 1.403031e+001 5.000000e+000 + vertex 4.267525e+001 1.471217e+001 4.399139e+000 + vertex 4.301727e+001 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal -2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 4.357020e+001 1.403031e+001 5.000000e+000 + vertex 4.307020e+001 1.489634e+001 4.399139e+000 + vertex 4.267525e+001 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 4.357020e+001 1.403031e+001 5.000000e+000 + vertex 4.406996e+001 1.438024e+001 5.000000e+000 + vertex 4.307020e+001 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 4.307020e+001 1.489634e+001 4.399139e+000 + vertex 4.406996e+001 1.438024e+001 5.000000e+000 + vertex 4.342717e+001 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal -3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 4.342717e+001 1.514629e+001 4.399139e+000 + vertex 4.406996e+001 1.438024e+001 5.000000e+000 + vertex 4.450136e+001 1.481164e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 4.373531e+001 1.545443e+001 4.399139e+000 + vertex 4.450136e+001 1.481164e+001 5.000000e+000 + vertex 4.485129e+001 1.531140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 4.398526e+001 1.581140e+001 4.399139e+000 + vertex 4.485129e+001 1.531140e+001 5.000000e+000 + vertex 4.510912e+001 1.586433e+001 5.000000e+000 + endloop + endfacet + facet normal -4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 4.416943e+001 1.620635e+001 4.399139e+000 + vertex 4.510912e+001 1.586433e+001 5.000000e+000 + vertex 4.428222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 4.416943e+001 1.620635e+001 4.399139e+000 + vertex 4.398526e+001 1.581140e+001 4.399139e+000 + vertex 4.510912e+001 1.586433e+001 5.000000e+000 + endloop + endfacet + facet normal -4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 4.510912e+001 1.586433e+001 5.000000e+000 + vertex 4.526703e+001 1.645363e+001 5.000000e+000 + vertex 4.428222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 4.428222e+001 1.662728e+001 4.399139e+000 + vertex 4.526703e+001 1.645363e+001 5.000000e+000 + vertex 4.432020e+001 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal -5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 4.432020e+001 1.706140e+001 4.399139e+000 + vertex 4.526703e+001 1.645363e+001 5.000000e+000 + vertex 4.532020e+001 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 4.428222e+001 1.749552e+001 4.399139e+000 + vertex 4.532020e+001 1.706140e+001 5.000000e+000 + vertex 4.526703e+001 1.766917e+001 5.000000e+000 + endloop + endfacet + facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 4.416943e+001 1.791645e+001 4.399139e+000 + vertex 4.526703e+001 1.766917e+001 5.000000e+000 + vertex 4.510912e+001 1.825847e+001 5.000000e+000 + endloop + endfacet + facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 4.398526e+001 1.831140e+001 4.399139e+000 + vertex 4.416943e+001 1.791645e+001 4.399139e+000 + vertex 4.510912e+001 1.825847e+001 5.000000e+000 + endloop + endfacet + facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 4.450136e+001 1.931116e+001 5.000000e+000 + vertex 4.406996e+001 1.974256e+001 5.000000e+000 + vertex 4.373531e+001 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 4.406996e+001 1.974256e+001 5.000000e+000 + vertex 4.357020e+001 2.009249e+001 5.000000e+000 + vertex 4.342717e+001 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 4.357020e+001 2.009249e+001 5.000000e+000 + vertex 4.301727e+001 2.035032e+001 5.000000e+000 + vertex 4.307020e+001 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 4.301727e+001 2.035032e+001 5.000000e+000 + vertex 4.242797e+001 2.050823e+001 5.000000e+000 + vertex 4.267525e+001 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 4.121243e+001 2.050823e+001 5.000000e+000 + vertex 4.062313e+001 2.035032e+001 5.000000e+000 + vertex 4.096515e+001 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 3.913904e+001 1.931116e+001 5.000000e+000 + vertex 3.878911e+001 1.881140e+001 5.000000e+000 + vertex 3.965514e+001 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 4.416943e+001 1.791645e+001 4.399139e+000 + vertex 4.428222e+001 1.749552e+001 4.399139e+000 + vertex 4.526703e+001 1.766917e+001 5.000000e+000 + endloop + endfacet + facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 4.428222e+001 1.749552e+001 4.399139e+000 + vertex 4.432020e+001 1.706140e+001 4.399139e+000 + vertex 4.532020e+001 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 4.398526e+001 1.581140e+001 4.399139e+000 + vertex 4.373531e+001 1.545443e+001 4.399139e+000 + vertex 4.485129e+001 1.531140e+001 5.000000e+000 + endloop + endfacet + facet normal -3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 4.342717e+001 1.514629e+001 4.399139e+000 + vertex 4.450136e+001 1.481164e+001 5.000000e+000 + vertex 4.373531e+001 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal -1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 4.267525e+001 1.471217e+001 4.399139e+000 + vertex 4.225432e+001 1.459938e+001 4.399139e+000 + vertex 4.242797e+001 1.361457e+001 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 4.225432e+001 1.459938e+001 4.399139e+000 + vertex 4.182020e+001 1.456140e+001 4.399139e+000 + vertex 4.182020e+001 1.356140e+001 5.000000e+000 + endloop + endfacet + facet normal -9.961947e-001 8.715574e-002 0.000000e+000 + outer loop + vertex 4.432020e+001 1.706140e+001 -8.881784e-016 + vertex 4.428222e+001 1.662728e+001 -8.881784e-016 + vertex 4.428222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.961947e-001 8.715574e-002 0.000000e+000 + outer loop + vertex 4.432020e+001 1.706140e+001 4.399139e+000 + vertex 4.432020e+001 1.706140e+001 -8.881784e-016 + vertex 4.428222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 + outer loop + vertex 4.432020e+001 1.706140e+001 4.399139e+000 + vertex 4.428222e+001 1.749552e+001 -8.881784e-016 + vertex 4.432020e+001 1.706140e+001 -8.881784e-016 + endloop + endfacet + facet normal -9.961947e-001 -8.715574e-002 -9.048915e-016 + outer loop + vertex 4.432020e+001 1.706140e+001 4.399139e+000 + vertex 4.428222e+001 1.749552e+001 4.399139e+000 + vertex 4.428222e+001 1.749552e+001 -8.881784e-016 + endloop + endfacet + facet normal -9.659258e-001 -2.588190e-001 5.300545e-016 + outer loop + vertex 4.428222e+001 1.749552e+001 -8.881784e-016 + vertex 4.428222e+001 1.749552e+001 4.399139e+000 + vertex 4.416943e+001 1.791645e+001 -8.881784e-016 + endloop + endfacet + facet normal -9.659258e-001 -2.588190e-001 -1.030095e-015 + outer loop + vertex 4.416943e+001 1.791645e+001 -8.881784e-016 + vertex 4.428222e+001 1.749552e+001 4.399139e+000 + vertex 4.416943e+001 1.791645e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 -4.226183e-001 1.440206e-016 + outer loop + vertex 4.398526e+001 1.831140e+001 -8.881784e-016 + vertex 4.416943e+001 1.791645e+001 4.399139e+000 + vertex 4.398526e+001 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 -5.735764e-001 -1.586601e-015 + outer loop + vertex 4.373531e+001 1.866837e+001 -8.881784e-016 + vertex 4.398526e+001 1.831140e+001 4.399139e+000 + vertex 4.373531e+001 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015 + outer loop + vertex 4.342717e+001 1.897651e+001 -8.881784e-016 + vertex 4.373531e+001 1.866837e+001 4.399139e+000 + vertex 4.342717e+001 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 -8.191520e-001 -1.324456e-015 + outer loop + vertex 4.307020e+001 1.922646e+001 -8.881784e-016 + vertex 4.342717e+001 1.897651e+001 4.399139e+000 + vertex 4.307020e+001 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 -9.063078e-001 -1.217252e-015 + outer loop + vertex 4.267525e+001 1.941063e+001 -8.881784e-016 + vertex 4.307020e+001 1.922646e+001 4.399139e+000 + vertex 4.267525e+001 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015 + outer loop + vertex 4.225432e+001 1.952342e+001 -8.881784e-016 + vertex 4.267525e+001 1.941063e+001 4.399139e+000 + vertex 4.225432e+001 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 + outer loop + vertex 4.182020e+001 1.956140e+001 -8.881784e-016 + vertex 4.225432e+001 1.952342e+001 4.399139e+000 + vertex 4.182020e+001 1.956140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016 + outer loop + vertex 4.138608e+001 1.952342e+001 -8.881784e-016 + vertex 4.182020e+001 1.956140e+001 4.399139e+000 + vertex 4.138608e+001 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 -9.659258e-001 -2.500203e-016 + outer loop + vertex 4.096515e+001 1.941063e+001 -8.881784e-016 + vertex 4.138608e+001 1.952342e+001 4.399139e+000 + vertex 4.096515e+001 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 -9.063078e-001 -9.292106e-016 + outer loop + vertex 4.057020e+001 1.922646e+001 -8.881784e-016 + vertex 4.096515e+001 1.941063e+001 4.399139e+000 + vertex 4.057020e+001 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 -8.191520e-001 -9.250596e-016 + outer loop + vertex 4.021323e+001 1.897651e+001 -8.881784e-016 + vertex 4.057020e+001 1.922646e+001 4.399139e+000 + vertex 4.021323e+001 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 -7.071068e-001 -1.142109e-015 + outer loop + vertex 3.990509e+001 1.866837e+001 -8.881784e-016 + vertex 4.021323e+001 1.897651e+001 4.399139e+000 + vertex 3.990509e+001 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 -5.735764e-001 -1.059565e-015 + outer loop + vertex 3.965514e+001 1.831140e+001 -8.881784e-016 + vertex 3.990509e+001 1.866837e+001 4.399139e+000 + vertex 3.965514e+001 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 -4.226183e-001 -4.853241e-016 + outer loop + vertex 3.947097e+001 1.791645e+001 -8.881784e-016 + vertex 3.965514e+001 1.831140e+001 4.399139e+000 + vertex 3.947097e+001 1.791645e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016 + outer loop + vertex 3.935818e+001 1.749552e+001 -8.881784e-016 + vertex 3.947097e+001 1.791645e+001 4.399139e+000 + vertex 3.935818e+001 1.749552e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 + outer loop + vertex 3.932020e+001 1.706140e+001 -8.881784e-016 + vertex 3.935818e+001 1.749552e+001 4.399139e+000 + vertex 3.932020e+001 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 8.715574e-002 7.038636e-017 + outer loop + vertex 3.935818e+001 1.662728e+001 -8.881784e-016 + vertex 3.932020e+001 1.706140e+001 4.399139e+000 + vertex 3.935818e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 2.588190e-001 0.000000e+000 + outer loop + vertex 3.947097e+001 1.620635e+001 -8.881784e-016 + vertex 3.935818e+001 1.662728e+001 4.399139e+000 + vertex 3.947097e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 4.226183e-001 0.000000e+000 + outer loop + vertex 3.965514e+001 1.581140e+001 -8.881784e-016 + vertex 3.947097e+001 1.620635e+001 4.399139e+000 + vertex 3.965514e+001 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 5.735764e-001 2.316081e-016 + outer loop + vertex 3.990509e+001 1.545443e+001 -8.881784e-016 + vertex 3.965514e+001 1.581140e+001 4.399139e+000 + vertex 3.990509e+001 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 7.071068e-001 2.855272e-016 + outer loop + vertex 4.021323e+001 1.514629e+001 -8.881784e-016 + vertex 3.990509e+001 1.545443e+001 4.399139e+000 + vertex 4.021323e+001 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 8.191520e-001 3.307707e-016 + outer loop + vertex 4.057020e+001 1.489634e+001 -8.881784e-016 + vertex 4.021323e+001 1.514629e+001 4.399139e+000 + vertex 4.057020e+001 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 9.063078e-001 -6.826070e-016 + outer loop + vertex 4.096515e+001 1.471217e+001 -8.881784e-016 + vertex 4.057020e+001 1.489634e+001 4.399139e+000 + vertex 4.096515e+001 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 9.659258e-001 -4.180408e-016 + outer loop + vertex 4.138608e+001 1.459938e+001 -8.881784e-016 + vertex 4.096515e+001 1.471217e+001 4.399139e+000 + vertex 4.138608e+001 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 9.961947e-001 0.000000e+000 + outer loop + vertex 4.182020e+001 1.456140e+001 -8.881784e-016 + vertex 4.138608e+001 1.459938e+001 4.399139e+000 + vertex 4.182020e+001 1.456140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 9.961947e-001 0.000000e+000 + outer loop + vertex 4.225432e+001 1.459938e+001 -8.881784e-016 + vertex 4.182020e+001 1.456140e+001 4.399139e+000 + vertex 4.225432e+001 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 9.659258e-001 2.800343e-017 + outer loop + vertex 4.267525e+001 1.471217e+001 -8.881784e-016 + vertex 4.225432e+001 1.459938e+001 4.399139e+000 + vertex 4.267525e+001 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 9.063078e-001 -3.659639e-016 + outer loop + vertex 4.307020e+001 1.489634e+001 -8.881784e-016 + vertex 4.267525e+001 1.471217e+001 4.399139e+000 + vertex 4.307020e+001 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 8.191520e-001 5.956618e-016 + outer loop + vertex 4.342717e+001 1.514629e+001 -8.881784e-016 + vertex 4.307020e+001 1.489634e+001 4.399139e+000 + vertex 4.342717e+001 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 7.071068e-001 0.000000e+000 + outer loop + vertex 4.373531e+001 1.545443e+001 -8.881784e-016 + vertex 4.342717e+001 1.514629e+001 4.399139e+000 + vertex 4.373531e+001 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 5.735764e-001 0.000000e+000 + outer loop + vertex 4.398526e+001 1.581140e+001 -8.881784e-016 + vertex 4.373531e+001 1.545443e+001 4.399139e+000 + vertex 4.398526e+001 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 4.226183e-001 0.000000e+000 + outer loop + vertex 4.416943e+001 1.620635e+001 -8.881784e-016 + vertex 4.398526e+001 1.581140e+001 4.399139e+000 + vertex 4.416943e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal -9.659258e-001 2.588190e-001 0.000000e+000 + outer loop + vertex 4.428222e+001 1.662728e+001 -8.881784e-016 + vertex 4.416943e+001 1.620635e+001 4.399139e+000 + vertex 4.428222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.659258e-001 2.588190e-001 0.000000e+000 + outer loop + vertex 4.428222e+001 1.662728e+001 -8.881784e-016 + vertex 4.416943e+001 1.620635e+001 -8.881784e-016 + vertex 4.416943e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 4.226183e-001 0.000000e+000 + outer loop + vertex 4.416943e+001 1.620635e+001 -8.881784e-016 + vertex 4.398526e+001 1.581140e+001 -8.881784e-016 + vertex 4.398526e+001 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 5.735764e-001 0.000000e+000 + outer loop + vertex 4.398526e+001 1.581140e+001 -8.881784e-016 + vertex 4.373531e+001 1.545443e+001 -8.881784e-016 + vertex 4.373531e+001 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 7.071068e-001 8.614567e-016 + outer loop + vertex 4.373531e+001 1.545443e+001 -8.881784e-016 + vertex 4.342717e+001 1.514629e+001 -8.881784e-016 + vertex 4.342717e+001 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 8.191520e-001 -3.257609e-016 + outer loop + vertex 4.342717e+001 1.514629e+001 -8.881784e-016 + vertex 4.307020e+001 1.489634e+001 -8.881784e-016 + vertex 4.307020e+001 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 9.063078e-001 3.166431e-016 + outer loop + vertex 4.267525e+001 1.471217e+001 -8.881784e-016 + vertex 4.267525e+001 1.471217e+001 4.399139e+000 + vertex 4.307020e+001 1.489634e+001 -8.881784e-016 + endloop + endfacet + facet normal -2.588190e-001 9.659258e-001 0.000000e+000 + outer loop + vertex 4.267525e+001 1.471217e+001 -8.881784e-016 + vertex 4.225432e+001 1.459938e+001 -8.881784e-016 + vertex 4.225432e+001 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 9.961947e-001 0.000000e+000 + outer loop + vertex 4.225432e+001 1.459938e+001 -8.881784e-016 + vertex 4.182020e+001 1.456140e+001 -8.881784e-016 + vertex 4.182020e+001 1.456140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 9.961947e-001 -1.411631e-016 + outer loop + vertex 4.182020e+001 1.456140e+001 -8.881784e-016 + vertex 4.138608e+001 1.459938e+001 -8.881784e-016 + vertex 4.138608e+001 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 9.659258e-001 -4.198697e-016 + outer loop + vertex 4.138608e+001 1.459938e+001 -8.881784e-016 + vertex 4.096515e+001 1.471217e+001 -8.881784e-016 + vertex 4.096515e+001 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 9.063078e-001 3.691957e-016 + outer loop + vertex 4.096515e+001 1.471217e+001 -8.881784e-016 + vertex 4.057020e+001 1.489634e+001 -8.881784e-016 + vertex 4.057020e+001 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 8.191520e-001 3.330001e-016 + outer loop + vertex 4.057020e+001 1.489634e+001 -8.881784e-016 + vertex 4.021323e+001 1.514629e+001 -8.881784e-016 + vertex 4.021323e+001 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 7.071068e-001 2.855272e-016 + outer loop + vertex 3.990509e+001 1.545443e+001 -8.881784e-016 + vertex 3.990509e+001 1.545443e+001 4.399139e+000 + vertex 4.021323e+001 1.514629e+001 -8.881784e-016 + endloop + endfacet + facet normal 8.191520e-001 5.735764e-001 0.000000e+000 + outer loop + vertex 3.990509e+001 1.545443e+001 -8.881784e-016 + vertex 3.965514e+001 1.581140e+001 -8.881784e-016 + vertex 3.965514e+001 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 4.226183e-001 0.000000e+000 + outer loop + vertex 3.965514e+001 1.581140e+001 -8.881784e-016 + vertex 3.947097e+001 1.620635e+001 -8.881784e-016 + vertex 3.947097e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 2.588190e-001 2.090204e-016 + outer loop + vertex 3.935818e+001 1.662728e+001 -8.881784e-016 + vertex 3.935818e+001 1.662728e+001 4.399139e+000 + vertex 3.947097e+001 1.620635e+001 -8.881784e-016 + endloop + endfacet + facet normal 9.961947e-001 8.715574e-002 7.040056e-016 + outer loop + vertex 3.935818e+001 1.662728e+001 -8.881784e-016 + vertex 3.932020e+001 1.706140e+001 -8.881784e-016 + vertex 3.932020e+001 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 -8.715574e-002 9.048915e-016 + outer loop + vertex 3.932020e+001 1.706140e+001 -8.881784e-016 + vertex 3.935818e+001 1.749552e+001 -8.881784e-016 + vertex 3.935818e+001 1.749552e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 -2.588190e-001 1.030095e-015 + outer loop + vertex 3.947097e+001 1.791645e+001 -8.881784e-016 + vertex 3.947097e+001 1.791645e+001 4.399139e+000 + vertex 3.935818e+001 1.749552e+001 -8.881784e-016 + endloop + endfacet + facet normal 9.063078e-001 -4.226183e-001 1.954566e-016 + outer loop + vertex 3.947097e+001 1.791645e+001 -8.881784e-016 + vertex 3.965514e+001 1.831140e+001 -8.881784e-016 + vertex 3.965514e+001 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 -5.735764e-001 2.606088e-016 + outer loop + vertex 3.965514e+001 1.831140e+001 -8.881784e-016 + vertex 3.990509e+001 1.866837e+001 -8.881784e-016 + vertex 3.990509e+001 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 -7.071068e-001 5.710544e-016 + outer loop + vertex 4.021323e+001 1.897651e+001 -8.881784e-016 + vertex 4.021323e+001 1.897651e+001 4.399139e+000 + vertex 3.990509e+001 1.866837e+001 -8.881784e-016 + endloop + endfacet + facet normal 5.735764e-001 -8.191520e-001 3.981523e-016 + outer loop + vertex 4.021323e+001 1.897651e+001 -8.881784e-016 + vertex 4.057020e+001 1.922646e+001 -8.881784e-016 + vertex 4.057020e+001 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 -9.063078e-001 1.216174e-015 + outer loop + vertex 4.057020e+001 1.922646e+001 -8.881784e-016 + vertex 4.096515e+001 1.941063e+001 -8.881784e-016 + vertex 4.096515e+001 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 -9.659258e-001 5.284567e-016 + outer loop + vertex 4.096515e+001 1.941063e+001 -8.881784e-016 + vertex 4.138608e+001 1.952342e+001 -8.881784e-016 + vertex 4.138608e+001 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 + outer loop + vertex 4.138608e+001 1.952342e+001 -8.881784e-016 + vertex 4.182020e+001 1.956140e+001 -8.881784e-016 + vertex 4.182020e+001 1.956140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 -9.961947e-001 1.013479e-016 + outer loop + vertex 4.182020e+001 1.956140e+001 -8.881784e-016 + vertex 4.225432e+001 1.952342e+001 -8.881784e-016 + vertex 4.225432e+001 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 -9.659258e-001 2.497501e-016 + outer loop + vertex 4.225432e+001 1.952342e+001 -8.881784e-016 + vertex 4.267525e+001 1.941063e+001 -8.881784e-016 + vertex 4.267525e+001 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 -9.063078e-001 2.461305e-016 + outer loop + vertex 4.267525e+001 1.941063e+001 -8.881784e-016 + vertex 4.307020e+001 1.922646e+001 -8.881784e-016 + vertex 4.307020e+001 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 -8.191520e-001 2.678479e-016 + outer loop + vertex 4.307020e+001 1.922646e+001 -8.881784e-016 + vertex 4.342717e+001 1.897651e+001 -8.881784e-016 + vertex 4.342717e+001 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 -7.071068e-001 0.000000e+000 + outer loop + vertex 4.342717e+001 1.897651e+001 -8.881784e-016 + vertex 4.373531e+001 1.866837e+001 -8.881784e-016 + vertex 4.373531e+001 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 -5.735764e-001 1.520218e-015 + outer loop + vertex 4.373531e+001 1.866837e+001 -8.881784e-016 + vertex 4.398526e+001 1.831140e+001 -8.881784e-016 + vertex 4.398526e+001 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 -4.226183e-001 4.850219e-016 + outer loop + vertex 4.398526e+001 1.831140e+001 -8.881784e-016 + vertex 4.416943e+001 1.791645e+001 -8.881784e-016 + vertex 4.416943e+001 1.791645e+001 4.399139e+000 + endloop + endfacet + facet normal 5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 2.137337e+001 1.245363e+001 5.000000e+000 + vertex 2.232020e+001 1.306140e+001 4.399139e+000 + vertex 2.132020e+001 1.306140e+001 5.000000e+000 + endloop + endfacet + facet normal 5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 2.137337e+001 1.245363e+001 5.000000e+000 + vertex 2.235818e+001 1.262728e+001 4.399139e+000 + vertex 2.232020e+001 1.306140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 2.137337e+001 1.245363e+001 5.000000e+000 + vertex 2.153128e+001 1.186433e+001 5.000000e+000 + vertex 2.235818e+001 1.262728e+001 4.399139e+000 + endloop + endfacet + facet normal 4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 2.235818e+001 1.262728e+001 4.399139e+000 + vertex 2.153128e+001 1.186433e+001 5.000000e+000 + vertex 2.247097e+001 1.220635e+001 4.399139e+000 + endloop + endfacet + facet normal 4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 2.247097e+001 1.220635e+001 4.399139e+000 + vertex 2.153128e+001 1.186433e+001 5.000000e+000 + vertex 2.178911e+001 1.131140e+001 5.000000e+000 + endloop + endfacet + facet normal 4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 2.265514e+001 1.181140e+001 4.399139e+000 + vertex 2.178911e+001 1.131140e+001 5.000000e+000 + vertex 2.213904e+001 1.081164e+001 5.000000e+000 + endloop + endfacet + facet normal 3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 2.290509e+001 1.145443e+001 4.399139e+000 + vertex 2.213904e+001 1.081164e+001 5.000000e+000 + vertex 2.257044e+001 1.038024e+001 5.000000e+000 + endloop + endfacet + facet normal 2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 2.321323e+001 1.114629e+001 4.399139e+000 + vertex 2.257044e+001 1.038024e+001 5.000000e+000 + vertex 2.307020e+001 1.003031e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 2.357020e+001 1.089634e+001 4.399139e+000 + vertex 2.307020e+001 1.003031e+001 5.000000e+000 + vertex 2.362313e+001 9.772476e+000 5.000000e+000 + endloop + endfacet + facet normal 1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 2.396515e+001 1.071217e+001 4.399139e+000 + vertex 2.362313e+001 9.772476e+000 5.000000e+000 + vertex 2.421243e+001 9.614573e+000 5.000000e+000 + endloop + endfacet + facet normal 4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 2.438608e+001 1.059938e+001 4.399139e+000 + vertex 2.421243e+001 9.614573e+000 5.000000e+000 + vertex 2.482020e+001 1.056140e+001 4.399139e+000 + endloop + endfacet + facet normal 1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 2.438608e+001 1.059938e+001 4.399139e+000 + vertex 2.396515e+001 1.071217e+001 4.399139e+000 + vertex 2.421243e+001 9.614573e+000 5.000000e+000 + endloop + endfacet + facet normal 4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 2.421243e+001 9.614573e+000 5.000000e+000 + vertex 2.482020e+001 9.561400e+000 5.000000e+000 + vertex 2.482020e+001 1.056140e+001 4.399139e+000 + endloop + endfacet + facet normal -4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 2.482020e+001 1.056140e+001 4.399139e+000 + vertex 2.482020e+001 9.561400e+000 5.000000e+000 + vertex 2.542797e+001 9.614573e+000 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 2.525432e+001 1.059938e+001 4.399139e+000 + vertex 2.542797e+001 9.614573e+000 5.000000e+000 + vertex 2.601727e+001 9.772476e+000 5.000000e+000 + endloop + endfacet + facet normal -2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 2.567525e+001 1.071217e+001 4.399139e+000 + vertex 2.601727e+001 9.772476e+000 5.000000e+000 + vertex 2.657020e+001 1.003031e+001 5.000000e+000 + endloop + endfacet + facet normal -2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 2.607020e+001 1.089634e+001 4.399139e+000 + vertex 2.657020e+001 1.003031e+001 5.000000e+000 + vertex 2.642717e+001 1.114629e+001 4.399139e+000 + endloop + endfacet + facet normal -2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 2.607020e+001 1.089634e+001 4.399139e+000 + vertex 2.567525e+001 1.071217e+001 4.399139e+000 + vertex 2.657020e+001 1.003031e+001 5.000000e+000 + endloop + endfacet + facet normal -2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 2.657020e+001 1.003031e+001 5.000000e+000 + vertex 2.706996e+001 1.038024e+001 5.000000e+000 + vertex 2.642717e+001 1.114629e+001 4.399139e+000 + endloop + endfacet + facet normal -3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 2.642717e+001 1.114629e+001 4.399139e+000 + vertex 2.706996e+001 1.038024e+001 5.000000e+000 + vertex 2.750136e+001 1.081164e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 2.673531e+001 1.145443e+001 4.399139e+000 + vertex 2.750136e+001 1.081164e+001 5.000000e+000 + vertex 2.785129e+001 1.131140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 2.698526e+001 1.181140e+001 4.399139e+000 + vertex 2.785129e+001 1.131140e+001 5.000000e+000 + vertex 2.810912e+001 1.186433e+001 5.000000e+000 + endloop + endfacet + facet normal -4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 2.716943e+001 1.220635e+001 4.399139e+000 + vertex 2.810912e+001 1.186433e+001 5.000000e+000 + vertex 2.826703e+001 1.245363e+001 5.000000e+000 + endloop + endfacet + facet normal -5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 2.728222e+001 1.262728e+001 4.399139e+000 + vertex 2.826703e+001 1.245363e+001 5.000000e+000 + vertex 2.832020e+001 1.306140e+001 5.000000e+000 + endloop + endfacet + facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 2.732020e+001 1.306140e+001 4.399139e+000 + vertex 2.832020e+001 1.306140e+001 5.000000e+000 + vertex 2.728222e+001 1.349552e+001 4.399139e+000 + endloop + endfacet + facet normal -5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 2.732020e+001 1.306140e+001 4.399139e+000 + vertex 2.728222e+001 1.262728e+001 4.399139e+000 + vertex 2.832020e+001 1.306140e+001 5.000000e+000 + endloop + endfacet + facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 2.832020e+001 1.306140e+001 5.000000e+000 + vertex 2.826703e+001 1.366917e+001 5.000000e+000 + vertex 2.728222e+001 1.349552e+001 4.399139e+000 + endloop + endfacet + facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 2.728222e+001 1.349552e+001 4.399139e+000 + vertex 2.826703e+001 1.366917e+001 5.000000e+000 + vertex 2.716943e+001 1.391645e+001 4.399139e+000 + endloop + endfacet + facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 2.716943e+001 1.391645e+001 4.399139e+000 + vertex 2.826703e+001 1.366917e+001 5.000000e+000 + vertex 2.810912e+001 1.425847e+001 5.000000e+000 + endloop + endfacet + facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 2.698526e+001 1.431140e+001 4.399139e+000 + vertex 2.810912e+001 1.425847e+001 5.000000e+000 + vertex 2.785129e+001 1.481140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 2.750136e+001 1.531116e+001 5.000000e+000 + vertex 2.698526e+001 1.431140e+001 4.399139e+000 + vertex 2.785129e+001 1.481140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 2.750136e+001 1.531116e+001 5.000000e+000 + vertex 2.673531e+001 1.466837e+001 4.399139e+000 + vertex 2.698526e+001 1.431140e+001 4.399139e+000 + endloop + endfacet + facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 2.750136e+001 1.531116e+001 5.000000e+000 + vertex 2.706996e+001 1.574256e+001 5.000000e+000 + vertex 2.673531e+001 1.466837e+001 4.399139e+000 + endloop + endfacet + facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 2.673531e+001 1.466837e+001 4.399139e+000 + vertex 2.706996e+001 1.574256e+001 5.000000e+000 + vertex 2.642717e+001 1.497651e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 2.642717e+001 1.497651e+001 4.399139e+000 + vertex 2.706996e+001 1.574256e+001 5.000000e+000 + vertex 2.607020e+001 1.522646e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 2.607020e+001 1.522646e+001 4.399139e+000 + vertex 2.706996e+001 1.574256e+001 5.000000e+000 + vertex 2.657020e+001 1.609249e+001 5.000000e+000 + endloop + endfacet + facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 2.567525e+001 1.541063e+001 4.399139e+000 + vertex 2.657020e+001 1.609249e+001 5.000000e+000 + vertex 2.601727e+001 1.635032e+001 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 2.525432e+001 1.552342e+001 4.399139e+000 + vertex 2.601727e+001 1.635032e+001 5.000000e+000 + vertex 2.542797e+001 1.650823e+001 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 2.482020e+001 1.656140e+001 5.000000e+000 + vertex 2.525432e+001 1.552342e+001 4.399139e+000 + vertex 2.542797e+001 1.650823e+001 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 2.482020e+001 1.656140e+001 5.000000e+000 + vertex 2.482020e+001 1.556140e+001 4.399139e+000 + vertex 2.525432e+001 1.552342e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 2.482020e+001 1.656140e+001 5.000000e+000 + vertex 2.421243e+001 1.650823e+001 5.000000e+000 + vertex 2.482020e+001 1.556140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 2.482020e+001 1.556140e+001 4.399139e+000 + vertex 2.421243e+001 1.650823e+001 5.000000e+000 + vertex 2.438608e+001 1.552342e+001 4.399139e+000 + endloop + endfacet + facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 2.438608e+001 1.552342e+001 4.399139e+000 + vertex 2.421243e+001 1.650823e+001 5.000000e+000 + vertex 2.362313e+001 1.635032e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 2.396515e+001 1.541063e+001 4.399139e+000 + vertex 2.362313e+001 1.635032e+001 5.000000e+000 + vertex 2.307020e+001 1.609249e+001 5.000000e+000 + endloop + endfacet + facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 2.357020e+001 1.522646e+001 4.399139e+000 + vertex 2.307020e+001 1.609249e+001 5.000000e+000 + vertex 2.321323e+001 1.497651e+001 4.399139e+000 + endloop + endfacet + facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 2.357020e+001 1.522646e+001 4.399139e+000 + vertex 2.396515e+001 1.541063e+001 4.399139e+000 + vertex 2.307020e+001 1.609249e+001 5.000000e+000 + endloop + endfacet + facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 2.321323e+001 1.497651e+001 4.399139e+000 + vertex 2.307020e+001 1.609249e+001 5.000000e+000 + vertex 2.257044e+001 1.574256e+001 5.000000e+000 + endloop + endfacet + facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 2.213904e+001 1.531116e+001 5.000000e+000 + vertex 2.321323e+001 1.497651e+001 4.399139e+000 + vertex 2.257044e+001 1.574256e+001 5.000000e+000 + endloop + endfacet + facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 2.213904e+001 1.531116e+001 5.000000e+000 + vertex 2.290509e+001 1.466837e+001 4.399139e+000 + vertex 2.321323e+001 1.497651e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 2.213904e+001 1.531116e+001 5.000000e+000 + vertex 2.178911e+001 1.481140e+001 5.000000e+000 + vertex 2.290509e+001 1.466837e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 2.290509e+001 1.466837e+001 4.399139e+000 + vertex 2.178911e+001 1.481140e+001 5.000000e+000 + vertex 2.265514e+001 1.431140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 2.265514e+001 1.431140e+001 4.399139e+000 + vertex 2.178911e+001 1.481140e+001 5.000000e+000 + vertex 2.153128e+001 1.425847e+001 5.000000e+000 + endloop + endfacet + facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 2.247097e+001 1.391645e+001 4.399139e+000 + vertex 2.153128e+001 1.425847e+001 5.000000e+000 + vertex 2.137337e+001 1.366917e+001 5.000000e+000 + endloop + endfacet + facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 2.235818e+001 1.349552e+001 4.399139e+000 + vertex 2.137337e+001 1.366917e+001 5.000000e+000 + vertex 2.132020e+001 1.306140e+001 5.000000e+000 + endloop + endfacet + facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 2.232020e+001 1.306140e+001 4.399139e+000 + vertex 2.235818e+001 1.349552e+001 4.399139e+000 + vertex 2.132020e+001 1.306140e+001 5.000000e+000 + endloop + endfacet + facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 2.235818e+001 1.349552e+001 4.399139e+000 + vertex 2.247097e+001 1.391645e+001 4.399139e+000 + vertex 2.137337e+001 1.366917e+001 5.000000e+000 + endloop + endfacet + facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 2.247097e+001 1.391645e+001 4.399139e+000 + vertex 2.265514e+001 1.431140e+001 4.399139e+000 + vertex 2.153128e+001 1.425847e+001 5.000000e+000 + endloop + endfacet + facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 2.396515e+001 1.541063e+001 4.399139e+000 + vertex 2.438608e+001 1.552342e+001 4.399139e+000 + vertex 2.362313e+001 1.635032e+001 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 2.525432e+001 1.552342e+001 4.399139e+000 + vertex 2.567525e+001 1.541063e+001 4.399139e+000 + vertex 2.601727e+001 1.635032e+001 5.000000e+000 + endloop + endfacet + facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 2.567525e+001 1.541063e+001 4.399139e+000 + vertex 2.607020e+001 1.522646e+001 4.399139e+000 + vertex 2.657020e+001 1.609249e+001 5.000000e+000 + endloop + endfacet + facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 2.698526e+001 1.431140e+001 4.399139e+000 + vertex 2.716943e+001 1.391645e+001 4.399139e+000 + vertex 2.810912e+001 1.425847e+001 5.000000e+000 + endloop + endfacet + facet normal -4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 2.728222e+001 1.262728e+001 4.399139e+000 + vertex 2.716943e+001 1.220635e+001 4.399139e+000 + vertex 2.826703e+001 1.245363e+001 5.000000e+000 + endloop + endfacet + facet normal -4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 2.716943e+001 1.220635e+001 4.399139e+000 + vertex 2.698526e+001 1.181140e+001 4.399139e+000 + vertex 2.810912e+001 1.186433e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 2.698526e+001 1.181140e+001 4.399139e+000 + vertex 2.673531e+001 1.145443e+001 4.399139e+000 + vertex 2.785129e+001 1.131140e+001 5.000000e+000 + endloop + endfacet + facet normal -3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 2.673531e+001 1.145443e+001 4.399139e+000 + vertex 2.642717e+001 1.114629e+001 4.399139e+000 + vertex 2.750136e+001 1.081164e+001 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 2.567525e+001 1.071217e+001 4.399139e+000 + vertex 2.525432e+001 1.059938e+001 4.399139e+000 + vertex 2.601727e+001 9.772476e+000 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 2.525432e+001 1.059938e+001 4.399139e+000 + vertex 2.482020e+001 1.056140e+001 4.399139e+000 + vertex 2.542797e+001 9.614573e+000 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 2.396515e+001 1.071217e+001 4.399139e+000 + vertex 2.357020e+001 1.089634e+001 4.399139e+000 + vertex 2.362313e+001 9.772476e+000 5.000000e+000 + endloop + endfacet + facet normal 2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 2.357020e+001 1.089634e+001 4.399139e+000 + vertex 2.321323e+001 1.114629e+001 4.399139e+000 + vertex 2.307020e+001 1.003031e+001 5.000000e+000 + endloop + endfacet + facet normal 3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 2.321323e+001 1.114629e+001 4.399139e+000 + vertex 2.290509e+001 1.145443e+001 4.399139e+000 + vertex 2.257044e+001 1.038024e+001 5.000000e+000 + endloop + endfacet + facet normal 4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 2.290509e+001 1.145443e+001 4.399139e+000 + vertex 2.265514e+001 1.181140e+001 4.399139e+000 + vertex 2.213904e+001 1.081164e+001 5.000000e+000 + endloop + endfacet + facet normal 4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 2.265514e+001 1.181140e+001 4.399139e+000 + vertex 2.247097e+001 1.220635e+001 4.399139e+000 + vertex 2.178911e+001 1.131140e+001 5.000000e+000 + endloop + endfacet + facet normal -9.961947e-001 8.715574e-002 -3.438588e-017 + outer loop + vertex 2.732020e+001 1.306140e+001 0.000000e+000 + vertex 2.728222e+001 1.262728e+001 0.000000e+000 + vertex 2.728222e+001 1.262728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.961947e-001 8.715574e-002 0.000000e+000 + outer loop + vertex 2.732020e+001 1.306140e+001 4.399139e+000 + vertex 2.732020e+001 1.306140e+001 0.000000e+000 + vertex 2.728222e+001 1.262728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 + outer loop + vertex 2.732020e+001 1.306140e+001 4.399139e+000 + vertex 2.728222e+001 1.349552e+001 0.000000e+000 + vertex 2.732020e+001 1.306140e+001 0.000000e+000 + endloop + endfacet + facet normal -9.961947e-001 -8.715574e-002 -6.515219e-017 + outer loop + vertex 2.732020e+001 1.306140e+001 4.399139e+000 + vertex 2.728222e+001 1.349552e+001 4.399139e+000 + vertex 2.728222e+001 1.349552e+001 0.000000e+000 + endloop + endfacet + facet normal -9.659258e-001 -2.588190e-001 1.414640e-015 + outer loop + vertex 2.728222e+001 1.349552e+001 0.000000e+000 + vertex 2.728222e+001 1.349552e+001 4.399139e+000 + vertex 2.716943e+001 1.391645e+001 0.000000e+000 + endloop + endfacet + facet normal -9.659258e-001 -2.588190e-001 -3.545305e-016 + outer loop + vertex 2.716943e+001 1.391645e+001 0.000000e+000 + vertex 2.728222e+001 1.349552e+001 4.399139e+000 + vertex 2.716943e+001 1.391645e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 -4.226183e-001 -7.585588e-016 + outer loop + vertex 2.698526e+001 1.431140e+001 0.000000e+000 + vertex 2.716943e+001 1.391645e+001 4.399139e+000 + vertex 2.698526e+001 1.431140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 -5.735764e-001 -2.635182e-016 + outer loop + vertex 2.673531e+001 1.466837e+001 0.000000e+000 + vertex 2.698526e+001 1.431140e+001 4.399139e+000 + vertex 2.673531e+001 1.466837e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 -7.071068e-001 -5.710544e-016 + outer loop + vertex 2.642717e+001 1.497651e+001 0.000000e+000 + vertex 2.673531e+001 1.466837e+001 4.399139e+000 + vertex 2.642717e+001 1.497651e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 -8.191520e-001 -8.612394e-016 + outer loop + vertex 2.607020e+001 1.522646e+001 0.000000e+000 + vertex 2.642717e+001 1.497651e+001 4.399139e+000 + vertex 2.607020e+001 1.522646e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 -9.063078e-001 -4.853241e-016 + outer loop + vertex 2.567525e+001 1.541063e+001 0.000000e+000 + vertex 2.607020e+001 1.522646e+001 4.399139e+000 + vertex 2.567525e+001 1.541063e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 -9.659258e-001 -5.300545e-016 + outer loop + vertex 2.525432e+001 1.552342e+001 0.000000e+000 + vertex 2.567525e+001 1.541063e+001 4.399139e+000 + vertex 2.525432e+001 1.552342e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 + outer loop + vertex 2.482020e+001 1.556140e+001 0.000000e+000 + vertex 2.525432e+001 1.552342e+001 4.399139e+000 + vertex 2.482020e+001 1.556140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 -9.961947e-001 -5.029161e-016 + outer loop + vertex 2.438608e+001 1.552342e+001 0.000000e+000 + vertex 2.482020e+001 1.556140e+001 4.399139e+000 + vertex 2.438608e+001 1.552342e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 -9.659258e-001 -6.400577e-016 + outer loop + vertex 2.396515e+001 1.541063e+001 0.000000e+000 + vertex 2.438608e+001 1.552342e+001 4.399139e+000 + vertex 2.396515e+001 1.541063e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 -9.063078e-001 -5.879071e-016 + outer loop + vertex 2.357020e+001 1.522646e+001 0.000000e+000 + vertex 2.396515e+001 1.541063e+001 4.399139e+000 + vertex 2.357020e+001 1.522646e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 -8.191520e-001 -5.942889e-016 + outer loop + vertex 2.321323e+001 1.497651e+001 0.000000e+000 + vertex 2.357020e+001 1.522646e+001 4.399139e+000 + vertex 2.321323e+001 1.497651e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 -7.071068e-001 -5.710544e-016 + outer loop + vertex 2.290509e+001 1.466837e+001 0.000000e+000 + vertex 2.321323e+001 1.497651e+001 4.399139e+000 + vertex 2.290509e+001 1.466837e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 -5.735764e-001 -8.612394e-016 + outer loop + vertex 2.265514e+001 1.431140e+001 0.000000e+000 + vertex 2.290509e+001 1.466837e+001 4.399139e+000 + vertex 2.265514e+001 1.431140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 -4.226183e-001 -3.146724e-016 + outer loop + vertex 2.247097e+001 1.391645e+001 0.000000e+000 + vertex 2.265514e+001 1.431140e+001 4.399139e+000 + vertex 2.247097e+001 1.391645e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016 + outer loop + vertex 2.235818e+001 1.349552e+001 0.000000e+000 + vertex 2.247097e+001 1.391645e+001 4.399139e+000 + vertex 2.235818e+001 1.349552e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 + outer loop + vertex 2.232020e+001 1.306140e+001 0.000000e+000 + vertex 2.235818e+001 1.349552e+001 4.399139e+000 + vertex 2.232020e+001 1.306140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 8.715574e-002 3.519318e-017 + outer loop + vertex 2.235818e+001 1.262728e+001 0.000000e+000 + vertex 2.232020e+001 1.306140e+001 4.399139e+000 + vertex 2.235818e+001 1.262728e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 2.588190e-001 -5.710544e-016 + outer loop + vertex 2.247097e+001 1.220635e+001 0.000000e+000 + vertex 2.235818e+001 1.262728e+001 4.399139e+000 + vertex 2.247097e+001 1.220635e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 4.226183e-001 1.706518e-016 + outer loop + vertex 2.265514e+001 1.181140e+001 0.000000e+000 + vertex 2.247097e+001 1.220635e+001 4.399139e+000 + vertex 2.265514e+001 1.181140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 5.735764e-001 2.316081e-016 + outer loop + vertex 2.290509e+001 1.145443e+001 0.000000e+000 + vertex 2.265514e+001 1.181140e+001 4.399139e+000 + vertex 2.290509e+001 1.145443e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 7.071068e-001 -2.855272e-016 + outer loop + vertex 2.321323e+001 1.114629e+001 0.000000e+000 + vertex 2.290509e+001 1.145443e+001 4.399139e+000 + vertex 2.321323e+001 1.114629e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 8.191520e-001 0.000000e+000 + outer loop + vertex 2.357020e+001 1.089634e+001 0.000000e+000 + vertex 2.321323e+001 1.114629e+001 4.399139e+000 + vertex 2.357020e+001 1.089634e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 9.063078e-001 -3.413035e-016 + outer loop + vertex 2.396515e+001 1.071217e+001 0.000000e+000 + vertex 2.357020e+001 1.089634e+001 4.399139e+000 + vertex 2.396515e+001 1.071217e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 9.659258e-001 -2.090204e-016 + outer loop + vertex 2.438608e+001 1.059938e+001 0.000000e+000 + vertex 2.396515e+001 1.071217e+001 4.399139e+000 + vertex 2.438608e+001 1.059938e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 9.961947e-001 -7.038636e-017 + outer loop + vertex 2.482020e+001 1.056140e+001 0.000000e+000 + vertex 2.438608e+001 1.059938e+001 4.399139e+000 + vertex 2.482020e+001 1.056140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 9.961947e-001 -3.318735e-016 + outer loop + vertex 2.525432e+001 1.059938e+001 0.000000e+000 + vertex 2.482020e+001 1.056140e+001 4.399139e+000 + vertex 2.525432e+001 1.059938e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 9.659258e-001 2.090204e-016 + outer loop + vertex 2.567525e+001 1.071217e+001 0.000000e+000 + vertex 2.525432e+001 1.059938e+001 4.399139e+000 + vertex 2.567525e+001 1.071217e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 9.063078e-001 0.000000e+000 + outer loop + vertex 2.607020e+001 1.089634e+001 0.000000e+000 + vertex 2.567525e+001 1.071217e+001 4.399139e+000 + vertex 2.607020e+001 1.089634e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 8.191520e-001 1.324456e-016 + outer loop + vertex 2.642717e+001 1.114629e+001 0.000000e+000 + vertex 2.607020e+001 1.089634e+001 4.399139e+000 + vertex 2.642717e+001 1.114629e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 7.071068e-001 5.710544e-016 + outer loop + vertex 2.673531e+001 1.145443e+001 0.000000e+000 + vertex 2.642717e+001 1.114629e+001 4.399139e+000 + vertex 2.673531e+001 1.145443e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 5.735764e-001 0.000000e+000 + outer loop + vertex 2.698526e+001 1.181140e+001 0.000000e+000 + vertex 2.673531e+001 1.145443e+001 4.399139e+000 + vertex 2.698526e+001 1.181140e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 4.226183e-001 -3.413035e-016 + outer loop + vertex 2.716943e+001 1.220635e+001 0.000000e+000 + vertex 2.698526e+001 1.181140e+001 4.399139e+000 + vertex 2.716943e+001 1.220635e+001 4.399139e+000 + endloop + endfacet + facet normal -9.659258e-001 2.588190e-001 -1.045102e-016 + outer loop + vertex 2.728222e+001 1.262728e+001 0.000000e+000 + vertex 2.716943e+001 1.220635e+001 4.399139e+000 + vertex 2.728222e+001 1.262728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.659258e-001 2.588190e-001 -2.063153e-016 + outer loop + vertex 2.728222e+001 1.262728e+001 0.000000e+000 + vertex 2.716943e+001 1.220635e+001 0.000000e+000 + vertex 2.716943e+001 1.220635e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 4.226183e-001 0.000000e+000 + outer loop + vertex 2.716943e+001 1.220635e+001 0.000000e+000 + vertex 2.698526e+001 1.181140e+001 0.000000e+000 + vertex 2.698526e+001 1.181140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 5.735764e-001 6.587610e-016 + outer loop + vertex 2.698526e+001 1.181140e+001 0.000000e+000 + vertex 2.673531e+001 1.145443e+001 0.000000e+000 + vertex 2.673531e+001 1.145443e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 7.071068e-001 2.895653e-016 + outer loop + vertex 2.673531e+001 1.145443e+001 0.000000e+000 + vertex 2.642717e+001 1.114629e+001 0.000000e+000 + vertex 2.642717e+001 1.114629e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 8.191520e-001 0.000000e+000 + outer loop + vertex 2.642717e+001 1.114629e+001 0.000000e+000 + vertex 2.607020e+001 1.089634e+001 0.000000e+000 + vertex 2.607020e+001 1.089634e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 9.063078e-001 3.402392e-016 + outer loop + vertex 2.607020e+001 1.089634e+001 0.000000e+000 + vertex 2.567525e+001 1.071217e+001 0.000000e+000 + vertex 2.567525e+001 1.071217e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 9.659258e-001 -1.845979e-016 + outer loop + vertex 2.567525e+001 1.071217e+001 0.000000e+000 + vertex 2.525432e+001 1.059938e+001 0.000000e+000 + vertex 2.525432e+001 1.059938e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 9.961947e-001 7.058154e-017 + outer loop + vertex 2.525432e+001 1.059938e+001 0.000000e+000 + vertex 2.482020e+001 1.056140e+001 0.000000e+000 + vertex 2.482020e+001 1.056140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 9.961947e-001 -7.058154e-017 + outer loop + vertex 2.482020e+001 1.056140e+001 0.000000e+000 + vertex 2.438608e+001 1.059938e+001 0.000000e+000 + vertex 2.438608e+001 1.059938e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 9.659258e-001 -2.099348e-016 + outer loop + vertex 2.438608e+001 1.059938e+001 0.000000e+000 + vertex 2.396515e+001 1.071217e+001 0.000000e+000 + vertex 2.396515e+001 1.071217e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 9.063078e-001 0.000000e+000 + outer loop + vertex 2.396515e+001 1.071217e+001 0.000000e+000 + vertex 2.357020e+001 1.089634e+001 0.000000e+000 + vertex 2.357020e+001 1.089634e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 8.191520e-001 -1.303044e-016 + outer loop + vertex 2.357020e+001 1.089634e+001 0.000000e+000 + vertex 2.321323e+001 1.114629e+001 0.000000e+000 + vertex 2.321323e+001 1.114629e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 7.071068e-001 2.895653e-016 + outer loop + vertex 2.321323e+001 1.114629e+001 0.000000e+000 + vertex 2.290509e+001 1.145443e+001 0.000000e+000 + vertex 2.290509e+001 1.145443e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 5.735764e-001 2.316522e-016 + outer loop + vertex 2.290509e+001 1.145443e+001 0.000000e+000 + vertex 2.265514e+001 1.181140e+001 0.000000e+000 + vertex 2.265514e+001 1.181140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 4.226183e-001 -3.909131e-016 + outer loop + vertex 2.265514e+001 1.181140e+001 0.000000e+000 + vertex 2.247097e+001 1.220635e+001 0.000000e+000 + vertex 2.247097e+001 1.220635e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 2.588190e-001 1.049674e-016 + outer loop + vertex 2.247097e+001 1.220635e+001 0.000000e+000 + vertex 2.235818e+001 1.262728e+001 0.000000e+000 + vertex 2.235818e+001 1.262728e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 8.715574e-002 7.040056e-016 + outer loop + vertex 2.235818e+001 1.262728e+001 0.000000e+000 + vertex 2.232020e+001 1.306140e+001 0.000000e+000 + vertex 2.232020e+001 1.306140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 -8.715574e-002 9.048915e-016 + outer loop + vertex 2.232020e+001 1.306140e+001 0.000000e+000 + vertex 2.235818e+001 1.349552e+001 0.000000e+000 + vertex 2.235818e+001 1.349552e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 -2.588190e-001 1.134605e-015 + outer loop + vertex 2.247097e+001 1.391645e+001 0.000000e+000 + vertex 2.247097e+001 1.391645e+001 4.399139e+000 + vertex 2.235818e+001 1.349552e+001 0.000000e+000 + endloop + endfacet + facet normal 9.063078e-001 -4.226183e-001 5.863697e-016 + outer loop + vertex 2.247097e+001 1.391645e+001 0.000000e+000 + vertex 2.265514e+001 1.431140e+001 0.000000e+000 + vertex 2.265514e+001 1.431140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 -5.735764e-001 9.266089e-016 + outer loop + vertex 2.265514e+001 1.431140e+001 0.000000e+000 + vertex 2.290509e+001 1.466837e+001 0.000000e+000 + vertex 2.290509e+001 1.466837e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 -7.071068e-001 8.542176e-016 + outer loop + vertex 2.290509e+001 1.466837e+001 0.000000e+000 + vertex 2.321323e+001 1.497651e+001 0.000000e+000 + vertex 2.321323e+001 1.497651e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 -8.191520e-001 8.612394e-016 + outer loop + vertex 2.357020e+001 1.522646e+001 0.000000e+000 + vertex 2.357020e+001 1.522646e+001 4.399139e+000 + vertex 2.321323e+001 1.497651e+001 0.000000e+000 + endloop + endfacet + facet normal 4.226183e-001 -9.063078e-001 8.542176e-016 + outer loop + vertex 2.357020e+001 1.522646e+001 0.000000e+000 + vertex 2.396515e+001 1.541063e+001 0.000000e+000 + vertex 2.396515e+001 1.541063e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 -9.659258e-001 9.193698e-016 + outer loop + vertex 2.396515e+001 1.541063e+001 0.000000e+000 + vertex 2.438608e+001 1.552342e+001 0.000000e+000 + vertex 2.438608e+001 1.552342e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 + outer loop + vertex 2.438608e+001 1.552342e+001 0.000000e+000 + vertex 2.482020e+001 1.556140e+001 0.000000e+000 + vertex 2.482020e+001 1.556140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 -9.961947e-001 9.051759e-016 + outer loop + vertex 2.525432e+001 1.552342e+001 0.000000e+000 + vertex 2.525432e+001 1.552342e+001 4.399139e+000 + vertex 2.482020e+001 1.556140e+001 0.000000e+000 + endloop + endfacet + facet normal -2.588190e-001 -9.659258e-001 1.031576e-015 + outer loop + vertex 2.525432e+001 1.552342e+001 0.000000e+000 + vertex 2.567525e+001 1.541063e+001 0.000000e+000 + vertex 2.567525e+001 1.541063e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 -9.063078e-001 5.863697e-016 + outer loop + vertex 2.567525e+001 1.541063e+001 0.000000e+000 + vertex 2.607020e+001 1.522646e+001 0.000000e+000 + vertex 2.607020e+001 1.522646e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 -8.191520e-001 9.266089e-016 + outer loop + vertex 2.607020e+001 1.522646e+001 0.000000e+000 + vertex 2.642717e+001 1.497651e+001 0.000000e+000 + vertex 2.642717e+001 1.497651e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 -7.071068e-001 1.143783e-015 + outer loop + vertex 2.642717e+001 1.497651e+001 0.000000e+000 + vertex 2.673531e+001 1.466837e+001 0.000000e+000 + vertex 2.673531e+001 1.466837e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 -5.735764e-001 6.298045e-016 + outer loop + vertex 2.673531e+001 1.466837e+001 0.000000e+000 + vertex 2.698526e+001 1.431140e+001 0.000000e+000 + vertex 2.698526e+001 1.431140e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 -4.226183e-001 1.049674e-015 + outer loop + vertex 2.698526e+001 1.431140e+001 0.000000e+000 + vertex 2.716943e+001 1.391645e+001 0.000000e+000 + vertex 2.716943e+001 1.391645e+001 4.399139e+000 + endloop + endfacet + facet normal 5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 4.320200e+000 1.706140e+001 5.000000e+000 + vertex 4.373373e+000 1.645363e+001 5.000000e+000 + vertex 5.320200e+000 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 5.358181e+000 1.749552e+001 4.399139e+000 + vertex 4.320200e+000 1.706140e+001 5.000000e+000 + vertex 5.320200e+000 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 5.358181e+000 1.749552e+001 4.399139e+000 + vertex 4.373373e+000 1.766917e+001 5.000000e+000 + vertex 4.320200e+000 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 5.358181e+000 1.749552e+001 4.399139e+000 + vertex 4.531276e+000 1.825847e+001 5.000000e+000 + vertex 4.373373e+000 1.766917e+001 5.000000e+000 + endloop + endfacet + facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 5.358181e+000 1.749552e+001 4.399139e+000 + vertex 5.470968e+000 1.791645e+001 4.399139e+000 + vertex 4.531276e+000 1.825847e+001 5.000000e+000 + endloop + endfacet + facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 4.531276e+000 1.825847e+001 5.000000e+000 + vertex 5.470968e+000 1.791645e+001 4.399139e+000 + vertex 4.789111e+000 1.881140e+001 5.000000e+000 + endloop + endfacet + facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 4.789111e+000 1.881140e+001 5.000000e+000 + vertex 5.470968e+000 1.791645e+001 4.399139e+000 + vertex 5.655136e+000 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 5.139044e+000 1.931116e+001 5.000000e+000 + vertex 5.655136e+000 1.831140e+001 4.399139e+000 + vertex 5.905089e+000 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 5.570443e+000 1.974256e+001 5.000000e+000 + vertex 5.905089e+000 1.866837e+001 4.399139e+000 + vertex 6.213231e+000 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 6.570200e+000 1.922646e+001 4.399139e+000 + vertex 5.570443e+000 1.974256e+001 5.000000e+000 + vertex 6.213231e+000 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 6.570200e+000 1.922646e+001 4.399139e+000 + vertex 6.070200e+000 2.009249e+001 5.000000e+000 + vertex 5.570443e+000 1.974256e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 6.570200e+000 1.922646e+001 4.399139e+000 + vertex 6.965150e+000 1.941063e+001 4.399139e+000 + vertex 6.070200e+000 2.009249e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 6.070200e+000 2.009249e+001 5.000000e+000 + vertex 6.965150e+000 1.941063e+001 4.399139e+000 + vertex 6.623129e+000 2.035032e+001 5.000000e+000 + endloop + endfacet + facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 6.623129e+000 2.035032e+001 5.000000e+000 + vertex 6.965150e+000 1.941063e+001 4.399139e+000 + vertex 7.212431e+000 2.050823e+001 5.000000e+000 + endloop + endfacet + facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 7.212431e+000 2.050823e+001 5.000000e+000 + vertex 6.965150e+000 1.941063e+001 4.399139e+000 + vertex 7.386080e+000 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 7.820200e+000 2.056140e+001 5.000000e+000 + vertex 7.386080e+000 1.952342e+001 4.399139e+000 + vertex 7.820200e+000 1.956140e+001 4.399139e+000 + endloop + endfacet + facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 8.427969e+000 2.050823e+001 5.000000e+000 + vertex 7.820200e+000 1.956140e+001 4.399139e+000 + vertex 8.254320e+000 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 9.017271e+000 2.035032e+001 5.000000e+000 + vertex 8.254320e+000 1.952342e+001 4.399139e+000 + vertex 8.675250e+000 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 9.570200e+000 2.009249e+001 5.000000e+000 + vertex 8.675250e+000 1.941063e+001 4.399139e+000 + vertex 9.070200e+000 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 1.006996e+001 1.974256e+001 5.000000e+000 + vertex 9.070200e+000 1.922646e+001 4.399139e+000 + vertex 9.427169e+000 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 9.735311e+000 1.866837e+001 4.399139e+000 + vertex 1.006996e+001 1.974256e+001 5.000000e+000 + vertex 9.427169e+000 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 9.735311e+000 1.866837e+001 4.399139e+000 + vertex 1.050136e+001 1.931116e+001 5.000000e+000 + vertex 1.006996e+001 1.974256e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 9.735311e+000 1.866837e+001 4.399139e+000 + vertex 9.985264e+000 1.831140e+001 4.399139e+000 + vertex 1.050136e+001 1.931116e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 1.050136e+001 1.931116e+001 5.000000e+000 + vertex 9.985264e+000 1.831140e+001 4.399139e+000 + vertex 1.085129e+001 1.881140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 1.085129e+001 1.881140e+001 5.000000e+000 + vertex 9.985264e+000 1.831140e+001 4.399139e+000 + vertex 1.016943e+001 1.791645e+001 4.399139e+000 + endloop + endfacet + facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 1.110912e+001 1.825847e+001 5.000000e+000 + vertex 1.016943e+001 1.791645e+001 4.399139e+000 + vertex 1.028222e+001 1.749552e+001 4.399139e+000 + endloop + endfacet + facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 1.126703e+001 1.766917e+001 5.000000e+000 + vertex 1.028222e+001 1.749552e+001 4.399139e+000 + vertex 1.132020e+001 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 + outer loop + vertex 1.126703e+001 1.766917e+001 5.000000e+000 + vertex 1.110912e+001 1.825847e+001 5.000000e+000 + vertex 1.028222e+001 1.749552e+001 4.399139e+000 + endloop + endfacet + facet normal 4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 4.531276e+000 1.586433e+001 5.000000e+000 + vertex 5.470968e+000 1.620635e+001 4.399139e+000 + vertex 4.373373e+000 1.645363e+001 5.000000e+000 + endloop + endfacet + facet normal 4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 4.531276e+000 1.586433e+001 5.000000e+000 + vertex 5.655136e+000 1.581140e+001 4.399139e+000 + vertex 5.470968e+000 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal 4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 4.531276e+000 1.586433e+001 5.000000e+000 + vertex 4.789111e+000 1.531140e+001 5.000000e+000 + vertex 5.655136e+000 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 5.655136e+000 1.581140e+001 4.399139e+000 + vertex 4.789111e+000 1.531140e+001 5.000000e+000 + vertex 5.905089e+000 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal 4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 5.905089e+000 1.545443e+001 4.399139e+000 + vertex 4.789111e+000 1.531140e+001 5.000000e+000 + vertex 5.139044e+000 1.481164e+001 5.000000e+000 + endloop + endfacet + facet normal 3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 6.213231e+000 1.514629e+001 4.399139e+000 + vertex 5.139044e+000 1.481164e+001 5.000000e+000 + vertex 5.570443e+000 1.438024e+001 5.000000e+000 + endloop + endfacet + facet normal 2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 6.570200e+000 1.489634e+001 4.399139e+000 + vertex 5.570443e+000 1.438024e+001 5.000000e+000 + vertex 6.070200e+000 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 6.623129e+000 1.377248e+001 5.000000e+000 + vertex 6.570200e+000 1.489634e+001 4.399139e+000 + vertex 6.070200e+000 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal 2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 6.623129e+000 1.377248e+001 5.000000e+000 + vertex 6.965150e+000 1.471217e+001 4.399139e+000 + vertex 6.570200e+000 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal 1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 6.623129e+000 1.377248e+001 5.000000e+000 + vertex 7.386080e+000 1.459938e+001 4.399139e+000 + vertex 6.965150e+000 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal 1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 6.623129e+000 1.377248e+001 5.000000e+000 + vertex 7.212431e+000 1.361457e+001 5.000000e+000 + vertex 7.386080e+000 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 7.386080e+000 1.459938e+001 4.399139e+000 + vertex 7.212431e+000 1.361457e+001 5.000000e+000 + vertex 7.820200e+000 1.356140e+001 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 7.820200e+000 1.456140e+001 4.399139e+000 + vertex 7.820200e+000 1.356140e+001 5.000000e+000 + vertex 8.427969e+000 1.361457e+001 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 8.254320e+000 1.459938e+001 4.399139e+000 + vertex 8.427969e+000 1.361457e+001 5.000000e+000 + vertex 9.017271e+000 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal -2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 8.675250e+000 1.471217e+001 4.399139e+000 + vertex 9.017271e+000 1.377248e+001 5.000000e+000 + vertex 9.570200e+000 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal -2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 9.070200e+000 1.489634e+001 4.399139e+000 + vertex 9.570200e+000 1.403031e+001 5.000000e+000 + vertex 1.006996e+001 1.438024e+001 5.000000e+000 + endloop + endfacet + facet normal -3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 9.427169e+000 1.514629e+001 4.399139e+000 + vertex 1.006996e+001 1.438024e+001 5.000000e+000 + vertex 1.050136e+001 1.481164e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 9.735311e+000 1.545443e+001 4.399139e+000 + vertex 1.050136e+001 1.481164e+001 5.000000e+000 + vertex 9.985264e+000 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal -3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 9.735311e+000 1.545443e+001 4.399139e+000 + vertex 9.427169e+000 1.514629e+001 4.399139e+000 + vertex 1.050136e+001 1.481164e+001 5.000000e+000 + endloop + endfacet + facet normal -4.230768e-001 2.962415e-001 8.562984e-001 + outer loop + vertex 1.050136e+001 1.481164e+001 5.000000e+000 + vertex 1.085129e+001 1.531140e+001 5.000000e+000 + vertex 9.985264e+000 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal -4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 9.985264e+000 1.581140e+001 4.399139e+000 + vertex 1.085129e+001 1.531140e+001 5.000000e+000 + vertex 1.016943e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal -4.680911e-001 2.182745e-001 8.562984e-001 + outer loop + vertex 1.016943e+001 1.620635e+001 4.399139e+000 + vertex 1.085129e+001 1.531140e+001 5.000000e+000 + vertex 1.110912e+001 1.586433e+001 5.000000e+000 + endloop + endfacet + facet normal -4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 1.126703e+001 1.645363e+001 5.000000e+000 + vertex 1.016943e+001 1.620635e+001 4.399139e+000 + vertex 1.110912e+001 1.586433e+001 5.000000e+000 + endloop + endfacet + facet normal -4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 1.126703e+001 1.645363e+001 5.000000e+000 + vertex 1.028222e+001 1.662728e+001 4.399139e+000 + vertex 1.016943e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal -5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 1.126703e+001 1.645363e+001 5.000000e+000 + vertex 1.132020e+001 1.706140e+001 5.000000e+000 + vertex 1.028222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 1.028222e+001 1.662728e+001 4.399139e+000 + vertex 1.132020e+001 1.706140e+001 5.000000e+000 + vertex 1.032020e+001 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 + outer loop + vertex 1.032020e+001 1.706140e+001 4.399139e+000 + vertex 1.132020e+001 1.706140e+001 5.000000e+000 + vertex 1.028222e+001 1.749552e+001 4.399139e+000 + endloop + endfacet + facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 + outer loop + vertex 1.110912e+001 1.825847e+001 5.000000e+000 + vertex 1.085129e+001 1.881140e+001 5.000000e+000 + vertex 1.016943e+001 1.791645e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 + outer loop + vertex 9.070200e+000 1.922646e+001 4.399139e+000 + vertex 1.006996e+001 1.974256e+001 5.000000e+000 + vertex 9.570200e+000 2.009249e+001 5.000000e+000 + endloop + endfacet + facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 + outer loop + vertex 9.017271e+000 2.035032e+001 5.000000e+000 + vertex 8.675250e+000 1.941063e+001 4.399139e+000 + vertex 9.570200e+000 2.009249e+001 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 + outer loop + vertex 9.017271e+000 2.035032e+001 5.000000e+000 + vertex 8.427969e+000 2.050823e+001 5.000000e+000 + vertex 8.254320e+000 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 8.427969e+000 2.050823e+001 5.000000e+000 + vertex 7.820200e+000 2.056140e+001 5.000000e+000 + vertex 7.820200e+000 1.956140e+001 4.399139e+000 + endloop + endfacet + facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 + outer loop + vertex 7.386080e+000 1.952342e+001 4.399139e+000 + vertex 7.820200e+000 2.056140e+001 5.000000e+000 + vertex 7.212431e+000 2.050823e+001 5.000000e+000 + endloop + endfacet + facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 + outer loop + vertex 5.139044e+000 1.931116e+001 5.000000e+000 + vertex 5.905089e+000 1.866837e+001 4.399139e+000 + vertex 5.570443e+000 1.974256e+001 5.000000e+000 + endloop + endfacet + facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 + outer loop + vertex 5.139044e+000 1.931116e+001 5.000000e+000 + vertex 4.789111e+000 1.881140e+001 5.000000e+000 + vertex 5.655136e+000 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal -2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 1.006996e+001 1.438024e+001 5.000000e+000 + vertex 9.427169e+000 1.514629e+001 4.399139e+000 + vertex 9.070200e+000 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal -2.182745e-001 4.680911e-001 8.562984e-001 + outer loop + vertex 9.070200e+000 1.489634e+001 4.399139e+000 + vertex 8.675250e+000 1.471217e+001 4.399139e+000 + vertex 9.570200e+000 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal -1.336752e-001 4.988827e-001 8.562984e-001 + outer loop + vertex 8.675250e+000 1.471217e+001 4.399139e+000 + vertex 8.254320e+000 1.459938e+001 4.399139e+000 + vertex 9.017271e+000 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal -4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 8.254320e+000 1.459938e+001 4.399139e+000 + vertex 7.820200e+000 1.456140e+001 4.399139e+000 + vertex 8.427969e+000 1.361457e+001 5.000000e+000 + endloop + endfacet + facet normal 4.501432e-002 5.145160e-001 8.562984e-001 + outer loop + vertex 7.820200e+000 1.456140e+001 4.399139e+000 + vertex 7.386080e+000 1.459938e+001 4.399139e+000 + vertex 7.820200e+000 1.356140e+001 5.000000e+000 + endloop + endfacet + facet normal 2.962415e-001 4.230768e-001 8.562984e-001 + outer loop + vertex 6.570200e+000 1.489634e+001 4.399139e+000 + vertex 6.213231e+000 1.514629e+001 4.399139e+000 + vertex 5.570443e+000 1.438024e+001 5.000000e+000 + endloop + endfacet + facet normal 3.652075e-001 3.652075e-001 8.562984e-001 + outer loop + vertex 5.139044e+000 1.481164e+001 5.000000e+000 + vertex 6.213231e+000 1.514629e+001 4.399139e+000 + vertex 5.905089e+000 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal 4.988827e-001 1.336752e-001 8.562984e-001 + outer loop + vertex 5.358181e+000 1.662728e+001 4.399139e+000 + vertex 4.373373e+000 1.645363e+001 5.000000e+000 + vertex 5.470968e+000 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal 5.145160e-001 4.501432e-002 8.562984e-001 + outer loop + vertex 5.358181e+000 1.662728e+001 4.399139e+000 + vertex 5.320200e+000 1.706140e+001 4.399139e+000 + vertex 4.373373e+000 1.645363e+001 5.000000e+000 + endloop + endfacet + facet normal -9.961947e-001 8.715574e-002 0.000000e+000 + outer loop + vertex 1.032020e+001 1.706140e+001 -8.881784e-016 + vertex 1.028222e+001 1.662728e+001 -8.881784e-016 + vertex 1.028222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.961947e-001 8.715574e-002 0.000000e+000 + outer loop + vertex 1.032020e+001 1.706140e+001 4.399139e+000 + vertex 1.032020e+001 1.706140e+001 -8.881784e-016 + vertex 1.028222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 + outer loop + vertex 1.032020e+001 1.706140e+001 4.399139e+000 + vertex 1.028222e+001 1.749552e+001 -8.881784e-016 + vertex 1.032020e+001 1.706140e+001 -8.881784e-016 + endloop + endfacet + facet normal -9.961947e-001 -8.715574e-002 -9.067013e-016 + outer loop + vertex 1.032020e+001 1.706140e+001 4.399139e+000 + vertex 1.028222e+001 1.749552e+001 4.399139e+000 + vertex 1.028222e+001 1.749552e+001 -8.881784e-016 + endloop + endfacet + facet normal -9.659258e-001 -2.588190e-001 5.300545e-016 + outer loop + vertex 1.028222e+001 1.749552e+001 -8.881784e-016 + vertex 1.028222e+001 1.749552e+001 4.399139e+000 + vertex 1.016943e+001 1.791645e+001 -8.881784e-016 + endloop + endfacet + facet normal -9.659258e-001 -2.588190e-001 -6.400577e-016 + outer loop + vertex 1.016943e+001 1.791645e+001 -8.881784e-016 + vertex 1.028222e+001 1.749552e+001 4.399139e+000 + vertex 1.016943e+001 1.791645e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 -4.226183e-001 -5.879071e-016 + outer loop + vertex 9.985264e+000 1.831140e+001 -8.881784e-016 + vertex 1.016943e+001 1.791645e+001 4.399139e+000 + vertex 9.985264e+000 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 -5.735764e-001 -5.942889e-016 + outer loop + vertex 9.735311e+000 1.866837e+001 -8.881784e-016 + vertex 9.985264e+000 1.831140e+001 4.399139e+000 + vertex 9.735311e+000 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015 + outer loop + vertex 9.427169e+000 1.897651e+001 -8.881784e-016 + vertex 9.735311e+000 1.866837e+001 4.399139e+000 + vertex 9.427169e+000 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 -8.191520e-001 -6.296313e-016 + outer loop + vertex 9.070200e+000 1.922646e+001 -8.881784e-016 + vertex 9.427169e+000 1.897651e+001 4.399139e+000 + vertex 9.070200e+000 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 -9.063078e-001 -1.046600e-015 + outer loop + vertex 8.675250e+000 1.941063e+001 -8.881784e-016 + vertex 9.070200e+000 1.922646e+001 4.399139e+000 + vertex 8.675250e+000 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015 + outer loop + vertex 8.254320e+000 1.952342e+001 -8.881784e-016 + vertex 8.675250e+000 1.941063e+001 4.399139e+000 + vertex 8.254320e+000 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 + outer loop + vertex 7.820200e+000 1.956140e+001 -8.881784e-016 + vertex 8.254320e+000 1.952342e+001 4.399139e+000 + vertex 7.820200e+000 1.956140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016 + outer loop + vertex 7.386080e+000 1.952342e+001 -8.881784e-016 + vertex 7.820200e+000 1.956140e+001 4.399139e+000 + vertex 7.386080e+000 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 -9.659258e-001 -3.545305e-016 + outer loop + vertex 6.965150e+000 1.941063e+001 -8.881784e-016 + vertex 7.386080e+000 1.952342e+001 4.399139e+000 + vertex 6.965150e+000 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 -9.063078e-001 -7.585588e-016 + outer loop + vertex 6.570200e+000 1.922646e+001 -8.881784e-016 + vertex 6.965150e+000 1.941063e+001 4.399139e+000 + vertex 6.570200e+000 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 -8.191520e-001 -1.040864e-015 + outer loop + vertex 6.213231e+000 1.897651e+001 -8.881784e-016 + vertex 6.570200e+000 1.922646e+001 4.399139e+000 + vertex 6.213231e+000 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 -7.071068e-001 -8.565816e-016 + outer loop + vertex 5.905089e+000 1.866837e+001 -8.881784e-016 + vertex 6.213231e+000 1.897651e+001 4.399139e+000 + vertex 5.905089e+000 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 -5.735764e-001 -3.980232e-016 + outer loop + vertex 5.655136e+000 1.831140e+001 -8.881784e-016 + vertex 5.905089e+000 1.866837e+001 4.399139e+000 + vertex 5.655136e+000 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 -4.226183e-001 -8.512880e-016 + outer loop + vertex 5.470968e+000 1.791645e+001 -8.881784e-016 + vertex 5.655136e+000 1.831140e+001 4.399139e+000 + vertex 5.470968e+000 1.791645e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 -2.588190e-001 -7.250733e-016 + outer loop + vertex 5.358181e+000 1.749552e+001 -8.881784e-016 + vertex 5.470968e+000 1.791645e+001 4.399139e+000 + vertex 5.358181e+000 1.749552e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 + outer loop + vertex 5.320200e+000 1.706140e+001 -8.881784e-016 + vertex 5.358181e+000 1.749552e+001 4.399139e+000 + vertex 5.320200e+000 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 8.715574e-002 7.038636e-017 + outer loop + vertex 5.358181e+000 1.662728e+001 -8.881784e-016 + vertex 5.320200e+000 1.706140e+001 4.399139e+000 + vertex 5.358181e+000 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 2.588190e-001 -3.900374e-016 + outer loop + vertex 5.470968e+000 1.620635e+001 -8.881784e-016 + vertex 5.358181e+000 1.662728e+001 4.399139e+000 + vertex 5.470968e+000 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 4.226183e-001 -1.829819e-016 + outer loop + vertex 5.655136e+000 1.581140e+001 -8.881784e-016 + vertex 5.470968e+000 1.620635e+001 4.399139e+000 + vertex 5.655136e+000 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 5.735764e-001 6.622278e-017 + outer loop + vertex 5.905089e+000 1.545443e+001 -8.881784e-016 + vertex 5.655136e+000 1.581140e+001 4.399139e+000 + vertex 5.905089e+000 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal 7.071068e-001 7.071068e-001 -6.583952e-030 + outer loop + vertex 6.213231e+000 1.514629e+001 -8.881784e-016 + vertex 5.905089e+000 1.545443e+001 4.399139e+000 + vertex 6.213231e+000 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 8.191520e-001 2.149666e-016 + outer loop + vertex 6.570200e+000 1.489634e+001 -8.881784e-016 + vertex 6.213231e+000 1.514629e+001 4.399139e+000 + vertex 6.570200e+000 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 9.063078e-001 -2.559776e-016 + outer loop + vertex 6.965150e+000 1.471217e+001 -8.881784e-016 + vertex 6.570200e+000 1.489634e+001 4.399139e+000 + vertex 6.965150e+000 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 9.659258e-001 -1.567653e-016 + outer loop + vertex 7.386080e+000 1.459938e+001 -8.881784e-016 + vertex 6.965150e+000 1.471217e+001 4.399139e+000 + vertex 7.386080e+000 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 9.961947e-001 -1.759659e-017 + outer loop + vertex 7.820200e+000 1.456140e+001 -8.881784e-016 + vertex 7.386080e+000 1.459938e+001 4.399139e+000 + vertex 7.820200e+000 1.456140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 9.961947e-001 7.038636e-017 + outer loop + vertex 8.254320e+000 1.459938e+001 -8.881784e-016 + vertex 7.820200e+000 1.456140e+001 4.399139e+000 + vertex 8.254320e+000 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 9.659258e-001 -2.855272e-016 + outer loop + vertex 8.675250e+000 1.471217e+001 -8.881784e-016 + vertex 8.254320e+000 1.459938e+001 4.399139e+000 + vertex 8.675250e+000 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 9.063078e-001 -1.953121e-016 + outer loop + vertex 9.070200e+000 1.489634e+001 -8.881784e-016 + vertex 8.675250e+000 1.471217e+001 4.399139e+000 + vertex 9.070200e+000 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 8.191520e-001 -9.916256e-017 + outer loop + vertex 9.427169e+000 1.514629e+001 -8.881784e-016 + vertex 9.070200e+000 1.489634e+001 4.399139e+000 + vertex 9.427169e+000 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 7.071068e-001 0.000000e+000 + outer loop + vertex 9.735311e+000 1.545443e+001 -8.881784e-016 + vertex 9.427169e+000 1.514629e+001 4.399139e+000 + vertex 9.735311e+000 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 5.735764e-001 0.000000e+000 + outer loop + vertex 9.985264e+000 1.581140e+001 -8.881784e-016 + vertex 9.735311e+000 1.545443e+001 4.399139e+000 + vertex 9.985264e+000 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 4.226183e-001 3.659639e-016 + outer loop + vertex 1.016943e+001 1.620635e+001 -8.881784e-016 + vertex 9.985264e+000 1.581140e+001 4.399139e+000 + vertex 1.016943e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal -9.659258e-001 2.588190e-001 0.000000e+000 + outer loop + vertex 1.028222e+001 1.662728e+001 -8.881784e-016 + vertex 1.016943e+001 1.620635e+001 4.399139e+000 + vertex 1.028222e+001 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal -9.659258e-001 2.588190e-001 3.909131e-016 + outer loop + vertex 1.028222e+001 1.662728e+001 -8.881784e-016 + vertex 1.016943e+001 1.620635e+001 -8.881784e-016 + vertex 1.016943e+001 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 4.226183e-001 0.000000e+000 + outer loop + vertex 1.016943e+001 1.620635e+001 -8.881784e-016 + vertex 9.985264e+000 1.581140e+001 -8.881784e-016 + vertex 9.985264e+000 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 5.735764e-001 0.000000e+000 + outer loop + vertex 9.985264e+000 1.581140e+001 -8.881784e-016 + vertex 9.735311e+000 1.545443e+001 -8.881784e-016 + vertex 9.735311e+000 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 7.071068e-001 0.000000e+000 + outer loop + vertex 9.735311e+000 1.545443e+001 -8.881784e-016 + vertex 9.427169e+000 1.514629e+001 -8.881784e-016 + vertex 9.427169e+000 1.514629e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 8.191520e-001 -9.410872e-017 + outer loop + vertex 9.427169e+000 1.514629e+001 -8.881784e-016 + vertex 9.070200e+000 1.489634e+001 -8.881784e-016 + vertex 9.070200e+000 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 9.063078e-001 -1.954566e-016 + outer loop + vertex 9.070200e+000 1.489634e+001 -8.881784e-016 + vertex 8.675250e+000 1.471217e+001 -8.881784e-016 + vertex 8.675250e+000 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 9.659258e-001 2.099348e-016 + outer loop + vertex 8.675250e+000 1.471217e+001 -8.881784e-016 + vertex 8.254320e+000 1.459938e+001 -8.881784e-016 + vertex 8.254320e+000 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 9.961947e-001 1.809783e-017 + outer loop + vertex 8.254320e+000 1.459938e+001 -8.881784e-016 + vertex 7.820200e+000 1.456140e+001 -8.881784e-016 + vertex 7.820200e+000 1.456140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.715574e-002 9.961947e-001 -5.429349e-017 + outer loop + vertex 7.820200e+000 1.456140e+001 -8.881784e-016 + vertex 7.386080e+000 1.459938e+001 -8.881784e-016 + vertex 7.386080e+000 1.459938e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 9.659258e-001 -1.592609e-016 + outer loop + vertex 7.386080e+000 1.459938e+001 -8.881784e-016 + vertex 6.965150e+000 1.471217e+001 -8.881784e-016 + vertex 6.965150e+000 1.471217e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 9.063078e-001 2.750870e-016 + outer loop + vertex 6.965150e+000 1.471217e+001 -8.881784e-016 + vertex 6.570200e+000 1.489634e+001 -8.881784e-016 + vertex 6.570200e+000 1.489634e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 8.191520e-001 9.916256e-017 + outer loop + vertex 6.213231e+000 1.514629e+001 -8.881784e-016 + vertex 6.213231e+000 1.514629e+001 4.399139e+000 + vertex 6.570200e+000 1.489634e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.071068e-001 7.071068e-001 1.447826e-016 + outer loop + vertex 6.213231e+000 1.514629e+001 -8.881784e-016 + vertex 5.905089e+000 1.545443e+001 -8.881784e-016 + vertex 5.905089e+000 1.545443e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 5.735764e-001 -1.592609e-016 + outer loop + vertex 5.905089e+000 1.545443e+001 -8.881784e-016 + vertex 5.655136e+000 1.581140e+001 -8.881784e-016 + vertex 5.655136e+000 1.581140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.063078e-001 4.226183e-001 -3.691957e-016 + outer loop + vertex 5.655136e+000 1.581140e+001 -8.881784e-016 + vertex 5.470968e+000 1.620635e+001 -8.881784e-016 + vertex 5.470968e+000 1.620635e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 2.588190e-001 2.099348e-016 + outer loop + vertex 5.470968e+000 1.620635e+001 -8.881784e-016 + vertex 5.358181e+000 1.662728e+001 -8.881784e-016 + vertex 5.358181e+000 1.662728e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 8.715574e-002 7.040056e-016 + outer loop + vertex 5.358181e+000 1.662728e+001 -8.881784e-016 + vertex 5.320200e+000 1.706140e+001 -8.881784e-016 + vertex 5.320200e+000 1.706140e+001 4.399139e+000 + endloop + endfacet + facet normal 9.961947e-001 -8.715574e-002 7.040056e-016 + outer loop + vertex 5.320200e+000 1.706140e+001 -8.881784e-016 + vertex 5.358181e+000 1.749552e+001 -8.881784e-016 + vertex 5.358181e+000 1.749552e+001 4.399139e+000 + endloop + endfacet + facet normal 9.659258e-001 -2.588190e-001 6.400577e-016 + outer loop + vertex 5.470968e+000 1.791645e+001 -8.881784e-016 + vertex 5.470968e+000 1.791645e+001 4.399139e+000 + vertex 5.358181e+000 1.749552e+001 -8.881784e-016 + endloop + endfacet + facet normal 9.063078e-001 -4.226183e-001 9.338481e-016 + outer loop + vertex 5.470968e+000 1.791645e+001 -8.881784e-016 + vertex 5.655136e+000 1.831140e+001 -8.881784e-016 + vertex 5.655136e+000 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal 8.191520e-001 -5.735764e-001 5.942889e-016 + outer loop + vertex 5.905089e+000 1.866837e+001 -8.881784e-016 + vertex 5.905089e+000 1.866837e+001 4.399139e+000 + vertex 5.655136e+000 1.831140e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.071068e-001 -7.071068e-001 4.271088e-016 + outer loop + vertex 5.905089e+000 1.866837e+001 -8.881784e-016 + vertex 6.213231e+000 1.897651e+001 -8.881784e-016 + vertex 6.213231e+000 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal 5.735764e-001 -8.191520e-001 6.298045e-016 + outer loop + vertex 6.213231e+000 1.897651e+001 -8.881784e-016 + vertex 6.570200e+000 1.922646e+001 -8.881784e-016 + vertex 6.570200e+000 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal 4.226183e-001 -9.063078e-001 1.049674e-015 + outer loop + vertex 6.570200e+000 1.922646e+001 -8.881784e-016 + vertex 6.965150e+000 1.941063e+001 -8.881784e-016 + vertex 6.965150e+000 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal 2.588190e-001 -9.659258e-001 5.300545e-016 + outer loop + vertex 7.386080e+000 1.952342e+001 -8.881784e-016 + vertex 7.386080e+000 1.952342e+001 4.399139e+000 + vertex 6.965150e+000 1.941063e+001 -8.881784e-016 + endloop + endfacet + facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 + outer loop + vertex 7.386080e+000 1.952342e+001 -8.881784e-016 + vertex 7.820200e+000 1.956140e+001 -8.881784e-016 + vertex 7.820200e+000 1.956140e+001 4.399139e+000 + endloop + endfacet + facet normal -8.715574e-002 -9.961947e-001 1.013479e-016 + outer loop + vertex 7.820200e+000 1.956140e+001 -8.881784e-016 + vertex 8.254320e+000 1.952342e+001 -8.881784e-016 + vertex 8.254320e+000 1.952342e+001 4.399139e+000 + endloop + endfacet + facet normal -2.588190e-001 -9.659258e-001 3.547175e-016 + outer loop + vertex 8.254320e+000 1.952342e+001 -8.881784e-016 + vertex 8.675250e+000 1.941063e+001 -8.881784e-016 + vertex 8.675250e+000 1.941063e+001 4.399139e+000 + endloop + endfacet + facet normal -4.226183e-001 -9.063078e-001 7.601089e-016 + outer loop + vertex 8.675250e+000 1.941063e+001 -8.881784e-016 + vertex 9.070200e+000 1.922646e+001 -8.881784e-016 + vertex 9.070200e+000 1.922646e+001 4.399139e+000 + endloop + endfacet + facet normal -5.735764e-001 -8.191520e-001 2.678479e-016 + outer loop + vertex 9.070200e+000 1.922646e+001 -8.881784e-016 + vertex 9.427169e+000 1.897651e+001 -8.881784e-016 + vertex 9.427169e+000 1.897651e+001 4.399139e+000 + endloop + endfacet + facet normal -7.071068e-001 -7.071068e-001 8.542176e-016 + outer loop + vertex 9.427169e+000 1.897651e+001 -8.881784e-016 + vertex 9.735311e+000 1.866837e+001 -8.881784e-016 + vertex 9.735311e+000 1.866837e+001 4.399139e+000 + endloop + endfacet + facet normal -8.191520e-001 -5.735764e-001 8.614567e-016 + outer loop + vertex 9.735311e+000 1.866837e+001 -8.881784e-016 + vertex 9.985264e+000 1.831140e+001 -8.881784e-016 + vertex 9.985264e+000 1.831140e+001 4.399139e+000 + endloop + endfacet + facet normal -9.063078e-001 -4.226183e-001 8.542176e-016 + outer loop + vertex 9.985264e+000 1.831140e+001 -8.881784e-016 + vertex 1.016943e+001 1.791645e+001 -8.881784e-016 + vertex 1.016943e+001 1.791645e+001 4.399139e+000 + endloop + endfacet + facet normal 4.639778e-016 9.961947e-001 -8.715574e-002 + outer loop + vertex -1.798000e-001 -2.938600e+000 5.000000e+000 + vertex -1.798000e-001 -2.893023e+000 5.520945e+000 + vertex 1.482020e+001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal -2.425509e-016 9.961947e-001 -8.715574e-002 + outer loop + vertex 1.482020e+001 -2.938600e+000 5.000000e+000 + vertex -1.798000e-001 -2.938600e+000 5.000000e+000 + vertex 1.482020e+001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal 2.425509e-016 9.961947e-001 8.715574e-002 + outer loop + vertex 1.482020e+001 -2.938600e+000 5.000000e+000 + vertex -1.798000e-001 -2.893023e+000 4.479055e+000 + vertex -1.798000e-001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -4.635355e-016 9.961947e-001 8.715574e-002 + outer loop + vertex 1.482020e+001 -2.938600e+000 5.000000e+000 + vertex 1.482020e+001 -2.893023e+000 4.479055e+000 + vertex -1.798000e-001 -2.893023e+000 4.479055e+000 + endloop + endfacet + facet normal 5.101317e-016 9.659258e-001 2.588190e-001 + outer loop + vertex -1.798000e-001 -2.893023e+000 4.479055e+000 + vertex 1.482020e+001 -2.893023e+000 4.479055e+000 + vertex -1.798000e-001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal -5.234721e-016 9.659258e-001 2.588190e-001 + outer loop + vertex -1.798000e-001 -2.757678e+000 3.973940e+000 + vertex 1.482020e+001 -2.893023e+000 4.479055e+000 + vertex 1.482020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal -4.809511e-016 9.063078e-001 4.226183e-001 + outer loop + vertex -1.798000e-001 -2.536676e+000 3.500000e+000 + vertex 1.482020e+001 -2.757678e+000 3.973940e+000 + vertex 1.482020e+001 -2.536676e+000 3.500000e+000 + endloop + endfacet + facet normal -5.134128e-016 8.191520e-001 5.735764e-001 + outer loop + vertex -1.798000e-001 -2.236733e+000 3.071637e+000 + vertex 1.482020e+001 -2.536676e+000 3.500000e+000 + vertex 1.482020e+001 -2.236733e+000 3.071637e+000 + endloop + endfacet + facet normal -5.024296e-016 7.071068e-001 7.071068e-001 + outer loop + vertex -1.798000e-001 -1.866963e+000 2.701867e+000 + vertex 1.482020e+001 -2.236733e+000 3.071637e+000 + vertex 1.482020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal -4.870609e-016 5.735764e-001 8.191520e-001 + outer loop + vertex -1.798000e-001 -1.438600e+000 2.401924e+000 + vertex 1.482020e+001 -1.866963e+000 2.701867e+000 + vertex 1.482020e+001 -1.438600e+000 2.401924e+000 + endloop + endfacet + facet normal -4.973720e-016 4.226183e-001 9.063078e-001 + outer loop + vertex -1.798000e-001 -9.646604e-001 2.180922e+000 + vertex 1.482020e+001 -1.438600e+000 2.401924e+000 + vertex 1.482020e+001 -9.646604e-001 2.180922e+000 + endloop + endfacet + facet normal -4.930284e-016 2.588190e-001 9.659258e-001 + outer loop + vertex -1.798000e-001 -4.595445e-001 2.045577e+000 + vertex 1.482020e+001 -9.646604e-001 2.180922e+000 + vertex 1.482020e+001 -4.595445e-001 2.045577e+000 + endloop + endfacet + facet normal -4.799411e-016 8.715574e-002 9.961947e-001 + outer loop + vertex -1.798000e-001 6.140000e-002 2.000000e+000 + vertex 1.482020e+001 -4.595445e-001 2.045577e+000 + vertex 1.482020e+001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal -4.933374e-016 -8.715574e-002 9.961947e-001 + outer loop + vertex -1.798000e-001 5.823445e-001 2.045577e+000 + vertex 1.482020e+001 6.140000e-002 2.000000e+000 + vertex 1.482020e+001 5.823445e-001 2.045577e+000 + endloop + endfacet + facet normal -4.872123e-016 -2.588190e-001 9.659258e-001 + outer loop + vertex -1.798000e-001 1.087460e+000 2.180922e+000 + vertex 1.482020e+001 5.823445e-001 2.045577e+000 + vertex 1.482020e+001 1.087460e+000 2.180922e+000 + endloop + endfacet + facet normal -4.809511e-016 -4.226183e-001 9.063078e-001 + outer loop + vertex -1.798000e-001 1.561400e+000 2.401924e+000 + vertex 1.482020e+001 1.087460e+000 2.180922e+000 + vertex 1.482020e+001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal -5.049222e-016 -5.735764e-001 8.191520e-001 + outer loop + vertex -1.798000e-001 1.989763e+000 2.701867e+000 + vertex 1.482020e+001 1.561400e+000 2.401924e+000 + vertex 1.482020e+001 1.989763e+000 2.701867e+000 + endloop + endfacet + facet normal -4.605605e-016 -7.071068e-001 7.071068e-001 + outer loop + vertex -1.798000e-001 2.359533e+000 3.071637e+000 + vertex 1.482020e+001 1.989763e+000 2.701867e+000 + vertex 1.482020e+001 2.359533e+000 3.071637e+000 + endloop + endfacet + facet normal -4.955515e-016 -8.191520e-001 5.735764e-001 + outer loop + vertex -1.798000e-001 2.659476e+000 3.500000e+000 + vertex 1.482020e+001 2.359533e+000 3.071637e+000 + vertex 1.482020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal -4.562199e-016 -9.063078e-001 4.226183e-001 + outer loop + vertex -1.798000e-001 2.880478e+000 3.973940e+000 + vertex 1.482020e+001 2.659476e+000 3.500000e+000 + vertex 1.482020e+001 2.880478e+000 3.973940e+000 + endloop + endfacet + facet normal -4.815345e-016 -9.659258e-001 2.588190e-001 + outer loop + vertex -1.798000e-001 3.015823e+000 4.479055e+000 + vertex 1.482020e+001 2.880478e+000 3.973940e+000 + vertex 1.482020e+001 3.015823e+000 4.479055e+000 + endloop + endfacet + facet normal -4.851017e-016 -9.961947e-001 8.715574e-002 + outer loop + vertex -1.798000e-001 3.061400e+000 5.000000e+000 + vertex 1.482020e+001 3.015823e+000 4.479055e+000 + vertex 1.482020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002 + outer loop + vertex -1.798000e-001 3.015823e+000 5.520945e+000 + vertex 1.482020e+001 3.061400e+000 5.000000e+000 + vertex 1.482020e+001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001 + outer loop + vertex -1.798000e-001 2.880478e+000 6.026060e+000 + vertex 1.482020e+001 3.015823e+000 5.520945e+000 + vertex 1.482020e+001 2.880478e+000 6.026060e+000 + endloop + endfacet + facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001 + outer loop + vertex -1.798000e-001 2.659476e+000 6.500000e+000 + vertex 1.482020e+001 2.880478e+000 6.026060e+000 + vertex 1.482020e+001 2.659476e+000 6.500000e+000 + endloop + endfacet + facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001 + outer loop + vertex -1.798000e-001 2.359533e+000 6.928363e+000 + vertex 1.482020e+001 2.659476e+000 6.500000e+000 + vertex 1.482020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001 + outer loop + vertex -1.798000e-001 1.989763e+000 7.298133e+000 + vertex 1.482020e+001 2.359533e+000 6.928363e+000 + vertex 1.482020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001 + outer loop + vertex -1.798000e-001 1.561400e+000 7.598076e+000 + vertex 1.482020e+001 1.989763e+000 7.298133e+000 + vertex 1.482020e+001 1.561400e+000 7.598076e+000 + endloop + endfacet + facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001 + outer loop + vertex -1.798000e-001 1.087460e+000 7.819078e+000 + vertex 1.482020e+001 1.561400e+000 7.598076e+000 + vertex 1.482020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001 + outer loop + vertex -1.798000e-001 5.823445e-001 7.954423e+000 + vertex 1.482020e+001 1.087460e+000 7.819078e+000 + vertex 1.482020e+001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001 + outer loop + vertex -1.798000e-001 6.140000e-002 8.000000e+000 + vertex 1.482020e+001 5.823445e-001 7.954423e+000 + vertex 1.482020e+001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal -5.189602e-016 8.715574e-002 -9.961947e-001 + outer loop + vertex -1.798000e-001 -4.595445e-001 7.954423e+000 + vertex 1.482020e+001 6.140000e-002 8.000000e+000 + vertex 1.482020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal -4.739404e-016 2.588190e-001 -9.659258e-001 + outer loop + vertex -1.798000e-001 -9.646604e-001 7.819078e+000 + vertex 1.482020e+001 -4.595445e-001 7.954423e+000 + vertex 1.482020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal -5.015272e-016 4.226183e-001 -9.063078e-001 + outer loop + vertex -1.798000e-001 -1.438600e+000 7.598076e+000 + vertex 1.482020e+001 -9.646604e-001 7.819078e+000 + vertex 1.482020e+001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal -4.479280e-016 5.735764e-001 -8.191520e-001 + outer loop + vertex -1.798000e-001 -1.866963e+000 7.298133e+000 + vertex 1.482020e+001 -1.438600e+000 7.598076e+000 + vertex 1.482020e+001 -1.866963e+000 7.298133e+000 + endloop + endfacet + facet normal -4.605605e-016 7.071068e-001 -7.071068e-001 + outer loop + vertex -1.798000e-001 -2.236733e+000 6.928363e+000 + vertex 1.482020e+001 -1.866963e+000 7.298133e+000 + vertex 1.482020e+001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal -4.955515e-016 8.191520e-001 -5.735764e-001 + outer loop + vertex -1.798000e-001 -2.536676e+000 6.500000e+000 + vertex 1.482020e+001 -2.236733e+000 6.928363e+000 + vertex 1.482020e+001 -2.536676e+000 6.500000e+000 + endloop + endfacet + facet normal -4.562199e-016 9.063078e-001 -4.226183e-001 + outer loop + vertex -1.798000e-001 -2.757678e+000 6.026060e+000 + vertex 1.482020e+001 -2.536676e+000 6.500000e+000 + vertex 1.482020e+001 -2.757678e+000 6.026060e+000 + endloop + endfacet + facet normal -5.101317e-016 9.659258e-001 -2.588190e-001 + outer loop + vertex -1.798000e-001 -2.893023e+000 5.520945e+000 + vertex 1.482020e+001 -2.757678e+000 6.026060e+000 + vertex 1.482020e+001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal 5.236890e-016 9.659258e-001 -2.588190e-001 + outer loop + vertex -1.798000e-001 -2.893023e+000 5.520945e+000 + vertex -1.798000e-001 -2.757678e+000 6.026060e+000 + vertex 1.482020e+001 -2.757678e+000 6.026060e+000 + endloop + endfacet + facet normal 4.688432e-016 9.063078e-001 -4.226183e-001 + outer loop + vertex -1.798000e-001 -2.757678e+000 6.026060e+000 + vertex -1.798000e-001 -2.536676e+000 6.500000e+000 + vertex 1.482020e+001 -2.536676e+000 6.500000e+000 + endloop + endfacet + facet normal 5.130737e-016 8.191520e-001 -5.735764e-001 + outer loop + vertex -1.798000e-001 -2.536676e+000 6.500000e+000 + vertex -1.798000e-001 -2.236733e+000 6.928363e+000 + vertex 1.482020e+001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal 5.236890e-016 7.071068e-001 -7.071068e-001 + outer loop + vertex -1.798000e-001 -2.236733e+000 6.928363e+000 + vertex -1.798000e-001 -1.866963e+000 7.298133e+000 + vertex 1.482020e+001 -1.866963e+000 7.298133e+000 + endloop + endfacet + facet normal 4.635355e-016 5.735764e-001 -8.191520e-001 + outer loop + vertex -1.798000e-001 -1.866963e+000 7.298133e+000 + vertex -1.798000e-001 -1.438600e+000 7.598076e+000 + vertex 1.482020e+001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal 4.971507e-016 4.226183e-001 -9.063078e-001 + outer loop + vertex -1.798000e-001 -1.438600e+000 7.598076e+000 + vertex -1.798000e-001 -9.646604e-001 7.819078e+000 + vertex 1.482020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal 4.635355e-016 2.588190e-001 -9.659258e-001 + outer loop + vertex -1.798000e-001 -9.646604e-001 7.819078e+000 + vertex -1.798000e-001 -4.595445e-001 7.954423e+000 + vertex 1.482020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal 4.799008e-016 8.715574e-002 -9.961947e-001 + outer loop + vertex -1.798000e-001 -4.595445e-001 7.954423e+000 + vertex -1.798000e-001 6.140000e-002 8.000000e+000 + vertex 1.482020e+001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001 + outer loop + vertex -1.798000e-001 6.140000e-002 8.000000e+000 + vertex -1.798000e-001 5.823445e-001 7.954423e+000 + vertex 1.482020e+001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001 + outer loop + vertex -1.798000e-001 5.823445e-001 7.954423e+000 + vertex -1.798000e-001 1.087460e+000 7.819078e+000 + vertex 1.482020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001 + outer loop + vertex -1.798000e-001 1.087460e+000 7.819078e+000 + vertex -1.798000e-001 1.561400e+000 7.598076e+000 + vertex 1.482020e+001 1.561400e+000 7.598076e+000 + endloop + endfacet + facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001 + outer loop + vertex -1.798000e-001 1.561400e+000 7.598076e+000 + vertex -1.798000e-001 1.989763e+000 7.298133e+000 + vertex 1.482020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001 + outer loop + vertex -1.798000e-001 1.989763e+000 7.298133e+000 + vertex -1.798000e-001 2.359533e+000 6.928363e+000 + vertex 1.482020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001 + outer loop + vertex -1.798000e-001 2.359533e+000 6.928363e+000 + vertex -1.798000e-001 2.659476e+000 6.500000e+000 + vertex 1.482020e+001 2.659476e+000 6.500000e+000 + endloop + endfacet + facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001 + outer loop + vertex -1.798000e-001 2.659476e+000 6.500000e+000 + vertex -1.798000e-001 2.880478e+000 6.026060e+000 + vertex 1.482020e+001 2.880478e+000 6.026060e+000 + endloop + endfacet + facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001 + outer loop + vertex -1.798000e-001 2.880478e+000 6.026060e+000 + vertex -1.798000e-001 3.015823e+000 5.520945e+000 + vertex 1.482020e+001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002 + outer loop + vertex -1.798000e-001 3.015823e+000 5.520945e+000 + vertex -1.798000e-001 3.061400e+000 5.000000e+000 + vertex 1.482020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 4.936122e-016 -9.961947e-001 8.715574e-002 + outer loop + vertex -1.798000e-001 3.061400e+000 5.000000e+000 + vertex -1.798000e-001 3.015823e+000 4.479055e+000 + vertex 1.482020e+001 3.015823e+000 4.479055e+000 + endloop + endfacet + facet normal 5.236890e-016 -9.659258e-001 2.588190e-001 + outer loop + vertex -1.798000e-001 3.015823e+000 4.479055e+000 + vertex -1.798000e-001 2.880478e+000 3.973940e+000 + vertex 1.482020e+001 2.880478e+000 3.973940e+000 + endloop + endfacet + facet normal 4.670740e-016 -9.063078e-001 4.226183e-001 + outer loop + vertex -1.798000e-001 2.880478e+000 3.973940e+000 + vertex -1.798000e-001 2.659476e+000 3.500000e+000 + vertex 1.482020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal 5.130737e-016 -8.191520e-001 5.735764e-001 + outer loop + vertex -1.798000e-001 2.659476e+000 3.500000e+000 + vertex -1.798000e-001 2.359533e+000 3.071637e+000 + vertex 1.482020e+001 2.359533e+000 3.071637e+000 + endloop + endfacet + facet normal 4.706124e-016 -7.071068e-001 7.071068e-001 + outer loop + vertex -1.798000e-001 2.359533e+000 3.071637e+000 + vertex -1.798000e-001 1.989763e+000 2.701867e+000 + vertex 1.482020e+001 1.989763e+000 2.701867e+000 + endloop + endfacet + facet normal 4.776893e-016 -5.735764e-001 8.191520e-001 + outer loop + vertex -1.798000e-001 1.989763e+000 2.701867e+000 + vertex -1.798000e-001 1.561400e+000 2.401924e+000 + vertex 1.482020e+001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal 4.953815e-016 -4.226183e-001 9.063078e-001 + outer loop + vertex -1.798000e-001 1.561400e+000 2.401924e+000 + vertex -1.798000e-001 1.087460e+000 2.180922e+000 + vertex 1.482020e+001 1.087460e+000 2.180922e+000 + endloop + endfacet + facet normal 4.812277e-016 -2.588190e-001 9.659258e-001 + outer loop + vertex -1.798000e-001 1.087460e+000 2.180922e+000 + vertex -1.798000e-001 5.823445e-001 2.045577e+000 + vertex 1.482020e+001 5.823445e-001 2.045577e+000 + endloop + endfacet + facet normal 4.799008e-016 -8.715574e-002 9.961947e-001 + outer loop + vertex -1.798000e-001 5.823445e-001 2.045577e+000 + vertex -1.798000e-001 6.140000e-002 2.000000e+000 + vertex 1.482020e+001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal 4.891892e-016 8.715574e-002 9.961947e-001 + outer loop + vertex -1.798000e-001 6.140000e-002 2.000000e+000 + vertex -1.798000e-001 -4.595445e-001 2.045577e+000 + vertex 1.482020e+001 -4.595445e-001 2.045577e+000 + endloop + endfacet + facet normal 4.741508e-016 2.588190e-001 9.659258e-001 + outer loop + vertex -1.798000e-001 -4.595445e-001 2.045577e+000 + vertex -1.798000e-001 -9.646604e-001 2.180922e+000 + vertex 1.482020e+001 -9.646604e-001 2.180922e+000 + endloop + endfacet + facet normal 4.759201e-016 4.226183e-001 9.063078e-001 + outer loop + vertex -1.798000e-001 -9.646604e-001 2.180922e+000 + vertex -1.798000e-001 -1.438600e+000 2.401924e+000 + vertex 1.482020e+001 -1.438600e+000 2.401924e+000 + endloop + endfacet + facet normal 4.706124e-016 5.735764e-001 8.191520e-001 + outer loop + vertex -1.798000e-001 -1.438600e+000 2.401924e+000 + vertex -1.798000e-001 -1.866963e+000 2.701867e+000 + vertex 1.482020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal 4.599971e-016 7.071068e-001 7.071068e-001 + outer loop + vertex -1.798000e-001 -1.866963e+000 2.701867e+000 + vertex -1.798000e-001 -2.236733e+000 3.071637e+000 + vertex 1.482020e+001 -2.236733e+000 3.071637e+000 + endloop + endfacet + facet normal 4.812277e-016 8.191520e-001 5.735764e-001 + outer loop + vertex -1.798000e-001 -2.236733e+000 3.071637e+000 + vertex -1.798000e-001 -2.536676e+000 3.500000e+000 + vertex 1.482020e+001 -2.536676e+000 3.500000e+000 + endloop + endfacet + facet normal 4.546894e-016 9.063078e-001 4.226183e-001 + outer loop + vertex -1.798000e-001 -2.536676e+000 3.500000e+000 + vertex -1.798000e-001 -2.757678e+000 3.973940e+000 + vertex 1.482020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal 4.639778e-016 9.961947e-001 -8.715574e-002 + outer loop + vertex 3.482020e+001 -2.938600e+000 5.000000e+000 + vertex 3.482020e+001 -2.893023e+000 5.520945e+000 + vertex 4.982020e+001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal -2.425509e-016 9.961947e-001 -8.715574e-002 + outer loop + vertex 4.982020e+001 -2.938600e+000 5.000000e+000 + vertex 3.482020e+001 -2.938600e+000 5.000000e+000 + vertex 4.982020e+001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal 2.425509e-016 9.961947e-001 8.715574e-002 + outer loop + vertex 4.982020e+001 -2.938600e+000 5.000000e+000 + vertex 3.482020e+001 -2.893023e+000 4.479055e+000 + vertex 3.482020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -4.635355e-016 9.961947e-001 8.715574e-002 + outer loop + vertex 4.982020e+001 -2.938600e+000 5.000000e+000 + vertex 4.982020e+001 -2.893023e+000 4.479055e+000 + vertex 3.482020e+001 -2.893023e+000 4.479055e+000 + endloop + endfacet + facet normal 5.101317e-016 9.659258e-001 2.588190e-001 + outer loop + vertex 3.482020e+001 -2.893023e+000 4.479055e+000 + vertex 4.982020e+001 -2.893023e+000 4.479055e+000 + vertex 3.482020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal -5.234721e-016 9.659258e-001 2.588190e-001 + outer loop + vertex 3.482020e+001 -2.757678e+000 3.973940e+000 + vertex 4.982020e+001 -2.893023e+000 4.479055e+000 + vertex 4.982020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal -4.809511e-016 9.063078e-001 4.226183e-001 + outer loop + vertex 3.482020e+001 -2.536676e+000 3.500000e+000 + vertex 4.982020e+001 -2.757678e+000 3.973940e+000 + vertex 4.982020e+001 -2.536676e+000 3.500000e+000 + endloop + endfacet + facet normal -5.134128e-016 8.191520e-001 5.735764e-001 + outer loop + vertex 3.482020e+001 -2.236733e+000 3.071637e+000 + vertex 4.982020e+001 -2.536676e+000 3.500000e+000 + vertex 4.982020e+001 -2.236733e+000 3.071637e+000 + endloop + endfacet + facet normal -5.024296e-016 7.071068e-001 7.071068e-001 + outer loop + vertex 3.482020e+001 -1.866963e+000 2.701867e+000 + vertex 4.982020e+001 -2.236733e+000 3.071637e+000 + vertex 4.982020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal -4.870609e-016 5.735764e-001 8.191520e-001 + outer loop + vertex 3.482020e+001 -1.438600e+000 2.401924e+000 + vertex 4.982020e+001 -1.866963e+000 2.701867e+000 + vertex 4.982020e+001 -1.438600e+000 2.401924e+000 + endloop + endfacet + facet normal -4.973720e-016 4.226183e-001 9.063078e-001 + outer loop + vertex 3.482020e+001 -9.646604e-001 2.180922e+000 + vertex 4.982020e+001 -1.438600e+000 2.401924e+000 + vertex 4.982020e+001 -9.646604e-001 2.180922e+000 + endloop + endfacet + facet normal -4.930284e-016 2.588190e-001 9.659258e-001 + outer loop + vertex 3.482020e+001 -4.595445e-001 2.045577e+000 + vertex 4.982020e+001 -9.646604e-001 2.180922e+000 + vertex 4.982020e+001 -4.595445e-001 2.045577e+000 + endloop + endfacet + facet normal -4.799411e-016 8.715574e-002 9.961947e-001 + outer loop + vertex 3.482020e+001 6.140000e-002 2.000000e+000 + vertex 4.982020e+001 -4.595445e-001 2.045577e+000 + vertex 4.982020e+001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal -4.933374e-016 -8.715574e-002 9.961947e-001 + outer loop + vertex 3.482020e+001 5.823445e-001 2.045577e+000 + vertex 4.982020e+001 6.140000e-002 2.000000e+000 + vertex 4.982020e+001 5.823445e-001 2.045577e+000 + endloop + endfacet + facet normal -4.872123e-016 -2.588190e-001 9.659258e-001 + outer loop + vertex 3.482020e+001 1.087460e+000 2.180922e+000 + vertex 4.982020e+001 5.823445e-001 2.045577e+000 + vertex 4.982020e+001 1.087460e+000 2.180922e+000 + endloop + endfacet + facet normal -4.809511e-016 -4.226183e-001 9.063078e-001 + outer loop + vertex 3.482020e+001 1.561400e+000 2.401924e+000 + vertex 4.982020e+001 1.087460e+000 2.180922e+000 + vertex 4.982020e+001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal -5.049222e-016 -5.735764e-001 8.191520e-001 + outer loop + vertex 3.482020e+001 1.989763e+000 2.701867e+000 + vertex 4.982020e+001 1.561400e+000 2.401924e+000 + vertex 4.982020e+001 1.989763e+000 2.701867e+000 + endloop + endfacet + facet normal -4.605605e-016 -7.071068e-001 7.071068e-001 + outer loop + vertex 3.482020e+001 2.359533e+000 3.071637e+000 + vertex 4.982020e+001 1.989763e+000 2.701867e+000 + vertex 4.982020e+001 2.359533e+000 3.071637e+000 + endloop + endfacet + facet normal -4.955515e-016 -8.191520e-001 5.735764e-001 + outer loop + vertex 3.482020e+001 2.659476e+000 3.500000e+000 + vertex 4.982020e+001 2.359533e+000 3.071637e+000 + vertex 4.982020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal -4.562199e-016 -9.063078e-001 4.226183e-001 + outer loop + vertex 3.482020e+001 2.880478e+000 3.973940e+000 + vertex 4.982020e+001 2.659476e+000 3.500000e+000 + vertex 4.982020e+001 2.880478e+000 3.973940e+000 + endloop + endfacet + facet normal -4.815345e-016 -9.659258e-001 2.588190e-001 + outer loop + vertex 3.482020e+001 3.015823e+000 4.479055e+000 + vertex 4.982020e+001 2.880478e+000 3.973940e+000 + vertex 4.982020e+001 3.015823e+000 4.479055e+000 + endloop + endfacet + facet normal -4.851017e-016 -9.961947e-001 8.715574e-002 + outer loop + vertex 3.482020e+001 3.061400e+000 5.000000e+000 + vertex 4.982020e+001 3.015823e+000 4.479055e+000 + vertex 4.982020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002 + outer loop + vertex 3.482020e+001 3.015823e+000 5.520945e+000 + vertex 4.982020e+001 3.061400e+000 5.000000e+000 + vertex 4.982020e+001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001 + outer loop + vertex 3.482020e+001 2.880478e+000 6.026060e+000 + vertex 4.982020e+001 3.015823e+000 5.520945e+000 + vertex 4.982020e+001 2.880478e+000 6.026060e+000 + endloop + endfacet + facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001 + outer loop + vertex 3.482020e+001 2.659476e+000 6.500000e+000 + vertex 4.982020e+001 2.880478e+000 6.026060e+000 + vertex 4.982020e+001 2.659476e+000 6.500000e+000 + endloop + endfacet + facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001 + outer loop + vertex 3.482020e+001 2.359533e+000 6.928363e+000 + vertex 4.982020e+001 2.659476e+000 6.500000e+000 + vertex 4.982020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001 + outer loop + vertex 3.482020e+001 1.989763e+000 7.298133e+000 + vertex 4.982020e+001 2.359533e+000 6.928363e+000 + vertex 4.982020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001 + outer loop + vertex 3.482020e+001 1.561400e+000 7.598076e+000 + vertex 4.982020e+001 1.989763e+000 7.298133e+000 + vertex 4.982020e+001 1.561400e+000 7.598076e+000 + endloop + endfacet + facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001 + outer loop + vertex 3.482020e+001 1.087460e+000 7.819078e+000 + vertex 4.982020e+001 1.561400e+000 7.598076e+000 + vertex 4.982020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001 + outer loop + vertex 3.482020e+001 5.823445e-001 7.954423e+000 + vertex 4.982020e+001 1.087460e+000 7.819078e+000 + vertex 4.982020e+001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001 + outer loop + vertex 3.482020e+001 6.140000e-002 8.000000e+000 + vertex 4.982020e+001 5.823445e-001 7.954423e+000 + vertex 4.982020e+001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal -5.189602e-016 8.715574e-002 -9.961947e-001 + outer loop + vertex 3.482020e+001 -4.595445e-001 7.954423e+000 + vertex 4.982020e+001 6.140000e-002 8.000000e+000 + vertex 4.982020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal -4.739404e-016 2.588190e-001 -9.659258e-001 + outer loop + vertex 3.482020e+001 -9.646604e-001 7.819078e+000 + vertex 4.982020e+001 -4.595445e-001 7.954423e+000 + vertex 4.982020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal -5.015272e-016 4.226183e-001 -9.063078e-001 + outer loop + vertex 3.482020e+001 -1.438600e+000 7.598076e+000 + vertex 4.982020e+001 -9.646604e-001 7.819078e+000 + vertex 4.982020e+001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal -4.479280e-016 5.735764e-001 -8.191520e-001 + outer loop + vertex 3.482020e+001 -1.866963e+000 7.298133e+000 + vertex 4.982020e+001 -1.438600e+000 7.598076e+000 + vertex 4.982020e+001 -1.866963e+000 7.298133e+000 + endloop + endfacet + facet normal -4.605605e-016 7.071068e-001 -7.071068e-001 + outer loop + vertex 3.482020e+001 -2.236733e+000 6.928363e+000 + vertex 4.982020e+001 -1.866963e+000 7.298133e+000 + vertex 4.982020e+001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal -4.955515e-016 8.191520e-001 -5.735764e-001 + outer loop + vertex 3.482020e+001 -2.536676e+000 6.500000e+000 + vertex 4.982020e+001 -2.236733e+000 6.928363e+000 + vertex 4.982020e+001 -2.536676e+000 6.500000e+000 + endloop + endfacet + facet normal -4.562199e-016 9.063078e-001 -4.226183e-001 + outer loop + vertex 3.482020e+001 -2.757678e+000 6.026060e+000 + vertex 4.982020e+001 -2.536676e+000 6.500000e+000 + vertex 4.982020e+001 -2.757678e+000 6.026060e+000 + endloop + endfacet + facet normal -5.101317e-016 9.659258e-001 -2.588190e-001 + outer loop + vertex 3.482020e+001 -2.893023e+000 5.520945e+000 + vertex 4.982020e+001 -2.757678e+000 6.026060e+000 + vertex 4.982020e+001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal 5.236890e-016 9.659258e-001 -2.588190e-001 + outer loop + vertex 3.482020e+001 -2.893023e+000 5.520945e+000 + vertex 3.482020e+001 -2.757678e+000 6.026060e+000 + vertex 4.982020e+001 -2.757678e+000 6.026060e+000 + endloop + endfacet + facet normal 4.688432e-016 9.063078e-001 -4.226183e-001 + outer loop + vertex 3.482020e+001 -2.757678e+000 6.026060e+000 + vertex 3.482020e+001 -2.536676e+000 6.500000e+000 + vertex 4.982020e+001 -2.536676e+000 6.500000e+000 + endloop + endfacet + facet normal 5.130737e-016 8.191520e-001 -5.735764e-001 + outer loop + vertex 3.482020e+001 -2.536676e+000 6.500000e+000 + vertex 3.482020e+001 -2.236733e+000 6.928363e+000 + vertex 4.982020e+001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal 5.236890e-016 7.071068e-001 -7.071068e-001 + outer loop + vertex 3.482020e+001 -2.236733e+000 6.928363e+000 + vertex 3.482020e+001 -1.866963e+000 7.298133e+000 + vertex 4.982020e+001 -1.866963e+000 7.298133e+000 + endloop + endfacet + facet normal 4.635355e-016 5.735764e-001 -8.191520e-001 + outer loop + vertex 3.482020e+001 -1.866963e+000 7.298133e+000 + vertex 3.482020e+001 -1.438600e+000 7.598076e+000 + vertex 4.982020e+001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal 4.971507e-016 4.226183e-001 -9.063078e-001 + outer loop + vertex 3.482020e+001 -1.438600e+000 7.598076e+000 + vertex 3.482020e+001 -9.646604e-001 7.819078e+000 + vertex 4.982020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal 4.635355e-016 2.588190e-001 -9.659258e-001 + outer loop + vertex 3.482020e+001 -9.646604e-001 7.819078e+000 + vertex 3.482020e+001 -4.595445e-001 7.954423e+000 + vertex 4.982020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal 4.799008e-016 8.715574e-002 -9.961947e-001 + outer loop + vertex 3.482020e+001 -4.595445e-001 7.954423e+000 + vertex 3.482020e+001 6.140000e-002 8.000000e+000 + vertex 4.982020e+001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001 + outer loop + vertex 3.482020e+001 6.140000e-002 8.000000e+000 + vertex 3.482020e+001 5.823445e-001 7.954423e+000 + vertex 4.982020e+001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001 + outer loop + vertex 3.482020e+001 5.823445e-001 7.954423e+000 + vertex 3.482020e+001 1.087460e+000 7.819078e+000 + vertex 4.982020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001 + outer loop + vertex 3.482020e+001 1.087460e+000 7.819078e+000 + vertex 3.482020e+001 1.561400e+000 7.598076e+000 + vertex 4.982020e+001 1.561400e+000 7.598076e+000 + endloop + endfacet + facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001 + outer loop + vertex 3.482020e+001 1.561400e+000 7.598076e+000 + vertex 3.482020e+001 1.989763e+000 7.298133e+000 + vertex 4.982020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001 + outer loop + vertex 3.482020e+001 1.989763e+000 7.298133e+000 + vertex 3.482020e+001 2.359533e+000 6.928363e+000 + vertex 4.982020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001 + outer loop + vertex 3.482020e+001 2.359533e+000 6.928363e+000 + vertex 3.482020e+001 2.659476e+000 6.500000e+000 + vertex 4.982020e+001 2.659476e+000 6.500000e+000 + endloop + endfacet + facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001 + outer loop + vertex 3.482020e+001 2.659476e+000 6.500000e+000 + vertex 3.482020e+001 2.880478e+000 6.026060e+000 + vertex 4.982020e+001 2.880478e+000 6.026060e+000 + endloop + endfacet + facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001 + outer loop + vertex 3.482020e+001 2.880478e+000 6.026060e+000 + vertex 3.482020e+001 3.015823e+000 5.520945e+000 + vertex 4.982020e+001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002 + outer loop + vertex 3.482020e+001 3.015823e+000 5.520945e+000 + vertex 3.482020e+001 3.061400e+000 5.000000e+000 + vertex 4.982020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 4.936122e-016 -9.961947e-001 8.715574e-002 + outer loop + vertex 3.482020e+001 3.061400e+000 5.000000e+000 + vertex 3.482020e+001 3.015823e+000 4.479055e+000 + vertex 4.982020e+001 3.015823e+000 4.479055e+000 + endloop + endfacet + facet normal 5.236890e-016 -9.659258e-001 2.588190e-001 + outer loop + vertex 3.482020e+001 3.015823e+000 4.479055e+000 + vertex 3.482020e+001 2.880478e+000 3.973940e+000 + vertex 4.982020e+001 2.880478e+000 3.973940e+000 + endloop + endfacet + facet normal 4.670740e-016 -9.063078e-001 4.226183e-001 + outer loop + vertex 3.482020e+001 2.880478e+000 3.973940e+000 + vertex 3.482020e+001 2.659476e+000 3.500000e+000 + vertex 4.982020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal 5.130737e-016 -8.191520e-001 5.735764e-001 + outer loop + vertex 3.482020e+001 2.659476e+000 3.500000e+000 + vertex 3.482020e+001 2.359533e+000 3.071637e+000 + vertex 4.982020e+001 2.359533e+000 3.071637e+000 + endloop + endfacet + facet normal 4.706124e-016 -7.071068e-001 7.071068e-001 + outer loop + vertex 3.482020e+001 2.359533e+000 3.071637e+000 + vertex 3.482020e+001 1.989763e+000 2.701867e+000 + vertex 4.982020e+001 1.989763e+000 2.701867e+000 + endloop + endfacet + facet normal 4.776893e-016 -5.735764e-001 8.191520e-001 + outer loop + vertex 3.482020e+001 1.989763e+000 2.701867e+000 + vertex 3.482020e+001 1.561400e+000 2.401924e+000 + vertex 4.982020e+001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal 4.953815e-016 -4.226183e-001 9.063078e-001 + outer loop + vertex 3.482020e+001 1.561400e+000 2.401924e+000 + vertex 3.482020e+001 1.087460e+000 2.180922e+000 + vertex 4.982020e+001 1.087460e+000 2.180922e+000 + endloop + endfacet + facet normal 4.812277e-016 -2.588190e-001 9.659258e-001 + outer loop + vertex 3.482020e+001 1.087460e+000 2.180922e+000 + vertex 3.482020e+001 5.823445e-001 2.045577e+000 + vertex 4.982020e+001 5.823445e-001 2.045577e+000 + endloop + endfacet + facet normal 4.799008e-016 -8.715574e-002 9.961947e-001 + outer loop + vertex 3.482020e+001 5.823445e-001 2.045577e+000 + vertex 3.482020e+001 6.140000e-002 2.000000e+000 + vertex 4.982020e+001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal 4.891892e-016 8.715574e-002 9.961947e-001 + outer loop + vertex 3.482020e+001 6.140000e-002 2.000000e+000 + vertex 3.482020e+001 -4.595445e-001 2.045577e+000 + vertex 4.982020e+001 -4.595445e-001 2.045577e+000 + endloop + endfacet + facet normal 4.741508e-016 2.588190e-001 9.659258e-001 + outer loop + vertex 3.482020e+001 -4.595445e-001 2.045577e+000 + vertex 3.482020e+001 -9.646604e-001 2.180922e+000 + vertex 4.982020e+001 -9.646604e-001 2.180922e+000 + endloop + endfacet + facet normal 4.759201e-016 4.226183e-001 9.063078e-001 + outer loop + vertex 3.482020e+001 -9.646604e-001 2.180922e+000 + vertex 3.482020e+001 -1.438600e+000 2.401924e+000 + vertex 4.982020e+001 -1.438600e+000 2.401924e+000 + endloop + endfacet + facet normal 4.706124e-016 5.735764e-001 8.191520e-001 + outer loop + vertex 3.482020e+001 -1.438600e+000 2.401924e+000 + vertex 3.482020e+001 -1.866963e+000 2.701867e+000 + vertex 4.982020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal 4.599971e-016 7.071068e-001 7.071068e-001 + outer loop + vertex 3.482020e+001 -1.866963e+000 2.701867e+000 + vertex 3.482020e+001 -2.236733e+000 3.071637e+000 + vertex 4.982020e+001 -2.236733e+000 3.071637e+000 + endloop + endfacet + facet normal 4.812277e-016 8.191520e-001 5.735764e-001 + outer loop + vertex 3.482020e+001 -2.236733e+000 3.071637e+000 + vertex 3.482020e+001 -2.536676e+000 3.500000e+000 + vertex 4.982020e+001 -2.536676e+000 3.500000e+000 + endloop + endfacet + facet normal 4.546894e-016 9.063078e-001 4.226183e-001 + outer loop + vertex 3.482020e+001 -2.536676e+000 3.500000e+000 + vertex 3.482020e+001 -2.757678e+000 3.973940e+000 + vertex 4.982020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.893023e+000 4.479055e+000 + vertex 3.482020e+001 -4.938600e+000 5.000000e+000 + vertex 3.482020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.893023e+000 4.479055e+000 + vertex 3.482020e+001 -4.862639e+000 4.131759e+000 + vertex 3.482020e+001 -4.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.893023e+000 4.479055e+000 + vertex 3.482020e+001 -2.757678e+000 3.973940e+000 + vertex 3.482020e+001 -4.862639e+000 4.131759e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.862639e+000 4.131759e+000 + vertex 3.482020e+001 -2.757678e+000 3.973940e+000 + vertex 3.482020e+001 -4.637063e+000 3.289899e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.637063e+000 3.289899e+000 + vertex 3.482020e+001 -2.757678e+000 3.973940e+000 + vertex 3.482020e+001 -2.536676e+000 3.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.268727e+000 2.500000e+000 + vertex 3.482020e+001 -2.536676e+000 3.500000e+000 + vertex 3.482020e+001 -2.236733e+000 3.071637e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -3.768822e+000 1.786062e+000 + vertex 3.482020e+001 -2.236733e+000 3.071637e+000 + vertex 3.482020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -3.152538e+000 1.169778e+000 + vertex 3.482020e+001 -1.866963e+000 2.701867e+000 + vertex 3.482020e+001 -2.438600e+000 6.698730e-001 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -3.152538e+000 1.169778e+000 + vertex 3.482020e+001 -3.768822e+000 1.786062e+000 + vertex 3.482020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -1.866963e+000 2.701867e+000 + vertex 3.482020e+001 -1.438600e+000 2.401924e+000 + vertex 3.482020e+001 -2.438600e+000 6.698730e-001 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.438600e+000 6.698730e-001 + vertex 3.482020e+001 -1.438600e+000 2.401924e+000 + vertex 3.482020e+001 -1.648701e+000 3.015369e-001 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -1.648701e+000 3.015369e-001 + vertex 3.482020e+001 -1.438600e+000 2.401924e+000 + vertex 3.482020e+001 -9.646604e-001 2.180922e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -8.068409e-001 7.596123e-002 + vertex 3.482020e+001 -9.646604e-001 2.180922e+000 + vertex 3.482020e+001 -4.595445e-001 2.045577e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 6.140000e-002 0.000000e+000 + vertex 3.482020e+001 -4.595445e-001 2.045577e+000 + vertex 3.482020e+001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.823445e-001 2.045577e+000 + vertex 3.482020e+001 6.140000e-002 0.000000e+000 + vertex 3.482020e+001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.823445e-001 2.045577e+000 + vertex 3.482020e+001 1.087460e+000 2.180922e+000 + vertex 3.482020e+001 6.140000e-002 0.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 6.140000e-002 0.000000e+000 + vertex 3.482020e+001 1.087460e+000 2.180922e+000 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 3.482020e+001 1.087460e+000 2.180922e+000 + vertex 3.482020e+001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 1.989763e+000 2.701867e+000 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 3.482020e+001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 1.989763e+000 2.701867e+000 + vertex 3.482020e+001 4.150665e+000 6.093379e-001 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 1.989763e+000 2.701867e+000 + vertex 3.482020e+001 2.359533e+000 3.071637e+000 + vertex 3.482020e+001 4.150665e+000 6.093379e-001 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 4.150665e+000 6.093379e-001 + vertex 3.482020e+001 2.359533e+000 3.071637e+000 + vertex 3.482020e+001 4.813319e+000 1.336768e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 4.813319e+000 1.336768e+000 + vertex 3.482020e+001 2.359533e+000 3.071637e+000 + vertex 3.482020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.348164e+000 2.162726e+000 + vertex 3.482020e+001 2.659476e+000 3.500000e+000 + vertex 3.482020e+001 2.880478e+000 3.973940e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.740815e+000 3.064995e+000 + vertex 3.482020e+001 2.880478e+000 3.973940e+000 + vertex 3.482020e+001 3.015823e+000 4.479055e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.061400e+000 5.000000e+000 + vertex 3.482020e+001 3.015823e+000 4.479055e+000 + vertex 3.482020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 3.015823e+000 5.520945e+000 + vertex 3.482020e+001 5.061400e+000 5.000000e+000 + vertex 3.482020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 3.015823e+000 5.520945e+000 + vertex 3.482020e+001 4.985439e+000 5.868241e+000 + vertex 3.482020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 3.015823e+000 5.520945e+000 + vertex 3.482020e+001 2.880478e+000 6.026060e+000 + vertex 3.482020e+001 4.985439e+000 5.868241e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 4.985439e+000 5.868241e+000 + vertex 3.482020e+001 2.880478e+000 6.026060e+000 + vertex 3.482020e+001 4.759863e+000 6.710101e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 4.759863e+000 6.710101e+000 + vertex 3.482020e+001 2.880478e+000 6.026060e+000 + vertex 3.482020e+001 2.659476e+000 6.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 4.391527e+000 7.500000e+000 + vertex 3.482020e+001 2.659476e+000 6.500000e+000 + vertex 3.482020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 3.891622e+000 8.213938e+000 + vertex 3.482020e+001 2.359533e+000 6.928363e+000 + vertex 3.482020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 3.275338e+000 8.830222e+000 + vertex 3.482020e+001 1.989763e+000 7.298133e+000 + vertex 3.482020e+001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 3.275338e+000 8.830222e+000 + vertex 3.482020e+001 3.891622e+000 8.213938e+000 + vertex 3.482020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 1.989763e+000 7.298133e+000 + vertex 3.482020e+001 1.561400e+000 7.598076e+000 + vertex 3.482020e+001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 2.561400e+000 9.330127e+000 + vertex 3.482020e+001 1.561400e+000 7.598076e+000 + vertex 3.482020e+001 1.771501e+000 9.698463e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 1.771501e+000 9.698463e+000 + vertex 3.482020e+001 1.561400e+000 7.598076e+000 + vertex 3.482020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 9.296409e-001 9.924039e+000 + vertex 3.482020e+001 1.087460e+000 7.819078e+000 + vertex 3.482020e+001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 6.140000e-002 1.000000e+001 + vertex 3.482020e+001 5.823445e-001 7.954423e+000 + vertex 3.482020e+001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -8.068409e-001 9.924039e+000 + vertex 3.482020e+001 6.140000e-002 8.000000e+000 + vertex 3.482020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -1.648701e+000 9.698463e+000 + vertex 3.482020e+001 -4.595445e-001 7.954423e+000 + vertex 3.482020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.438600e+000 9.330127e+000 + vertex 3.482020e+001 -9.646604e-001 7.819078e+000 + vertex 3.482020e+001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -3.152538e+000 8.830222e+000 + vertex 3.482020e+001 -1.438600e+000 7.598076e+000 + vertex 3.482020e+001 -1.866963e+000 7.298133e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.236733e+000 6.928363e+000 + vertex 3.482020e+001 -3.152538e+000 8.830222e+000 + vertex 3.482020e+001 -1.866963e+000 7.298133e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.236733e+000 6.928363e+000 + vertex 3.482020e+001 -3.768822e+000 8.213938e+000 + vertex 3.482020e+001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.236733e+000 6.928363e+000 + vertex 3.482020e+001 -2.536676e+000 6.500000e+000 + vertex 3.482020e+001 -3.768822e+000 8.213938e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -3.768822e+000 8.213938e+000 + vertex 3.482020e+001 -2.536676e+000 6.500000e+000 + vertex 3.482020e+001 -4.268727e+000 7.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.268727e+000 7.500000e+000 + vertex 3.482020e+001 -2.536676e+000 6.500000e+000 + vertex 3.482020e+001 -2.757678e+000 6.026060e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.637063e+000 6.710101e+000 + vertex 3.482020e+001 -2.757678e+000 6.026060e+000 + vertex 3.482020e+001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.862639e+000 5.868241e+000 + vertex 3.482020e+001 -2.893023e+000 5.520945e+000 + vertex 3.482020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.938600e+000 5.000000e+000 + vertex 3.482020e+001 -4.862639e+000 5.868241e+000 + vertex 3.482020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.061400e+000 5.000000e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 3.482020e+001 5.980711e+000 4.019309e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.740815e+000 3.064995e+000 + vertex 3.482020e+001 5.061400e+000 5.000000e+000 + vertex 3.482020e+001 5.980711e+000 4.019309e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.740815e+000 3.064995e+000 + vertex 3.482020e+001 3.015823e+000 4.479055e+000 + vertex 3.482020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.740815e+000 3.064995e+000 + vertex 3.482020e+001 5.348164e+000 2.162726e+000 + vertex 3.482020e+001 2.880478e+000 3.973940e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 5.348164e+000 2.162726e+000 + vertex 3.482020e+001 4.813319e+000 1.336768e+000 + vertex 3.482020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 6.140000e-002 0.000000e+000 + vertex 3.482020e+001 -8.068409e-001 7.596123e-002 + vertex 3.482020e+001 -4.595445e-001 2.045577e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -1.648701e+000 3.015369e-001 + vertex 3.482020e+001 -9.646604e-001 2.180922e+000 + vertex 3.482020e+001 -8.068409e-001 7.596123e-002 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -3.768822e+000 1.786062e+000 + vertex 3.482020e+001 -4.268727e+000 2.500000e+000 + vertex 3.482020e+001 -2.236733e+000 3.071637e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.268727e+000 2.500000e+000 + vertex 3.482020e+001 -4.637063e+000 3.289899e+000 + vertex 3.482020e+001 -2.536676e+000 3.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.862639e+000 5.868241e+000 + vertex 3.482020e+001 -4.637063e+000 6.710101e+000 + vertex 3.482020e+001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -4.637063e+000 6.710101e+000 + vertex 3.482020e+001 -4.268727e+000 7.500000e+000 + vertex 3.482020e+001 -2.757678e+000 6.026060e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -3.152538e+000 8.830222e+000 + vertex 3.482020e+001 -2.438600e+000 9.330127e+000 + vertex 3.482020e+001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -2.438600e+000 9.330127e+000 + vertex 3.482020e+001 -1.648701e+000 9.698463e+000 + vertex 3.482020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 -1.648701e+000 9.698463e+000 + vertex 3.482020e+001 -8.068409e-001 9.924039e+000 + vertex 3.482020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 6.140000e-002 1.000000e+001 + vertex 3.482020e+001 6.140000e-002 8.000000e+000 + vertex 3.482020e+001 -8.068409e-001 9.924039e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 9.296409e-001 9.924039e+000 + vertex 3.482020e+001 5.823445e-001 7.954423e+000 + vertex 3.482020e+001 6.140000e-002 1.000000e+001 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 1.771501e+000 9.698463e+000 + vertex 3.482020e+001 1.087460e+000 7.819078e+000 + vertex 3.482020e+001 9.296409e-001 9.924039e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 2.359533e+000 6.928363e+000 + vertex 3.482020e+001 3.891622e+000 8.213938e+000 + vertex 3.482020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 3.482020e+001 4.759863e+000 6.710101e+000 + vertex 3.482020e+001 2.659476e+000 6.500000e+000 + vertex 3.482020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.966323e-001 8.200039e-002 + outer loop + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex 1.482020e+001 5.980711e+000 4.019309e+000 + endloop + endfacet + facet normal -4.306895e-017 -9.698266e-001 2.437957e-001 + outer loop + vertex 3.482020e+001 5.980711e+000 4.019309e+000 + vertex 1.482020e+001 5.980711e+000 4.019309e+000 + vertex 3.482020e+001 5.740815e+000 3.064995e+000 + endloop + endfacet + facet normal -4.425936e-017 -9.966323e-001 8.200039e-002 + outer loop + vertex 3.482020e+001 5.980711e+000 4.019309e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 1.482020e+001 5.980711e+000 4.019309e+000 + endloop + endfacet + facet normal 1.692405e-017 -9.698266e-001 2.437957e-001 + outer loop + vertex 1.482020e+001 5.980711e+000 4.019309e+000 + vertex 1.482020e+001 5.740815e+000 3.064995e+000 + vertex 3.482020e+001 5.740815e+000 3.064995e+000 + endloop + endfacet + facet normal -3.581497e-018 -9.169362e-001 3.990338e-001 + outer loop + vertex 3.482020e+001 5.740815e+000 3.064995e+000 + vertex 1.482020e+001 5.740815e+000 3.064995e+000 + vertex 3.482020e+001 5.348164e+000 2.162726e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.169362e-001 3.990338e-001 + outer loop + vertex 3.482020e+001 5.348164e+000 2.162726e+000 + vertex 1.482020e+001 5.740815e+000 3.064995e+000 + vertex 1.482020e+001 5.348164e+000 2.162726e+000 + endloop + endfacet + facet normal 1.313813e-017 -8.393837e-001 5.435393e-001 + outer loop + vertex 3.482020e+001 4.813319e+000 1.336768e+000 + vertex 1.482020e+001 5.348164e+000 2.162726e+000 + vertex 1.482020e+001 4.813319e+000 1.336768e+000 + endloop + endfacet + facet normal 0.000000e+000 -7.392549e-001 6.734257e-001 + outer loop + vertex 3.482020e+001 4.150665e+000 6.093379e-001 + vertex 1.482020e+001 4.813319e+000 1.336768e+000 + vertex 1.482020e+001 4.150665e+000 6.093379e-001 + endloop + endfacet + facet normal 0.000000e+000 -6.192429e-001 7.851995e-001 + outer loop + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 1.482020e+001 4.150665e+000 6.093379e-001 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 -6.192429e-001 7.851995e-001 + outer loop + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 3.482020e+001 4.150665e+000 6.093379e-001 + vertex 1.482020e+001 4.150665e+000 6.093379e-001 + endloop + endfacet + facet normal 2.820675e-018 -7.392549e-001 6.734257e-001 + outer loop + vertex 3.482020e+001 4.150665e+000 6.093379e-001 + vertex 3.482020e+001 4.813319e+000 1.336768e+000 + vertex 1.482020e+001 4.813319e+000 1.336768e+000 + endloop + endfacet + facet normal 0.000000e+000 -8.393837e-001 5.435393e-001 + outer loop + vertex 3.482020e+001 4.813319e+000 1.336768e+000 + vertex 3.482020e+001 5.348164e+000 2.162726e+000 + vertex 1.482020e+001 5.348164e+000 2.162726e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -2.893023e+000 5.520945e+000 + vertex 1.482020e+001 -4.862639e+000 5.868241e+000 + vertex 1.482020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -2.893023e+000 5.520945e+000 + vertex 1.482020e+001 -4.637063e+000 6.710101e+000 + vertex 1.482020e+001 -4.862639e+000 5.868241e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -2.893023e+000 5.520945e+000 + vertex 1.482020e+001 -2.757678e+000 6.026060e+000 + vertex 1.482020e+001 -4.637063e+000 6.710101e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.637063e+000 6.710101e+000 + vertex 1.482020e+001 -2.757678e+000 6.026060e+000 + vertex 1.482020e+001 -4.268727e+000 7.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.268727e+000 7.500000e+000 + vertex 1.482020e+001 -2.757678e+000 6.026060e+000 + vertex 1.482020e+001 -2.536676e+000 6.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -3.768822e+000 8.213938e+000 + vertex 1.482020e+001 -2.536676e+000 6.500000e+000 + vertex 1.482020e+001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -1.866963e+000 7.298133e+000 + vertex 1.482020e+001 -3.768822e+000 8.213938e+000 + vertex 1.482020e+001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -1.866963e+000 7.298133e+000 + vertex 1.482020e+001 -3.152538e+000 8.830222e+000 + vertex 1.482020e+001 -3.768822e+000 8.213938e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -1.866963e+000 7.298133e+000 + vertex 1.482020e+001 -1.438600e+000 7.598076e+000 + vertex 1.482020e+001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -3.152538e+000 8.830222e+000 + vertex 1.482020e+001 -1.438600e+000 7.598076e+000 + vertex 1.482020e+001 -2.438600e+000 9.330127e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -2.438600e+000 9.330127e+000 + vertex 1.482020e+001 -1.438600e+000 7.598076e+000 + vertex 1.482020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -1.648701e+000 9.698463e+000 + vertex 1.482020e+001 -9.646604e-001 7.819078e+000 + vertex 1.482020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -8.068409e-001 9.924039e+000 + vertex 1.482020e+001 -4.595445e-001 7.954423e+000 + vertex 1.482020e+001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 6.140000e-002 1.000000e+001 + vertex 1.482020e+001 6.140000e-002 8.000000e+000 + vertex 1.482020e+001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 9.296409e-001 9.924039e+000 + vertex 1.482020e+001 5.823445e-001 7.954423e+000 + vertex 1.482020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 1.771501e+000 9.698463e+000 + vertex 1.482020e+001 1.087460e+000 7.819078e+000 + vertex 1.482020e+001 1.561400e+000 7.598076e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 2.561400e+000 9.330127e+000 + vertex 1.482020e+001 1.561400e+000 7.598076e+000 + vertex 1.482020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 3.275338e+000 8.830222e+000 + vertex 1.482020e+001 1.989763e+000 7.298133e+000 + vertex 1.482020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 3.891622e+000 8.213938e+000 + vertex 1.482020e+001 2.359533e+000 6.928363e+000 + vertex 1.482020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 3.891622e+000 8.213938e+000 + vertex 1.482020e+001 3.275338e+000 8.830222e+000 + vertex 1.482020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 2.659476e+000 6.500000e+000 + vertex 1.482020e+001 4.391527e+000 7.500000e+000 + vertex 1.482020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 2.659476e+000 6.500000e+000 + vertex 1.482020e+001 4.759863e+000 6.710101e+000 + vertex 1.482020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 2.659476e+000 6.500000e+000 + vertex 1.482020e+001 2.880478e+000 6.026060e+000 + vertex 1.482020e+001 4.759863e+000 6.710101e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 4.759863e+000 6.710101e+000 + vertex 1.482020e+001 2.880478e+000 6.026060e+000 + vertex 1.482020e+001 4.985439e+000 5.868241e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 4.985439e+000 5.868241e+000 + vertex 1.482020e+001 2.880478e+000 6.026060e+000 + vertex 1.482020e+001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + vertex 1.482020e+001 3.015823e+000 5.520945e+000 + vertex 1.482020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 3.015823e+000 4.479055e+000 + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + vertex 1.482020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 3.015823e+000 4.479055e+000 + vertex 1.482020e+001 5.740815e+000 3.064995e+000 + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 3.015823e+000 4.479055e+000 + vertex 1.482020e+001 2.880478e+000 3.973940e+000 + vertex 1.482020e+001 5.740815e+000 3.064995e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 5.740815e+000 3.064995e+000 + vertex 1.482020e+001 2.880478e+000 3.973940e+000 + vertex 1.482020e+001 5.348164e+000 2.162726e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 5.348164e+000 2.162726e+000 + vertex 1.482020e+001 2.880478e+000 3.973940e+000 + vertex 1.482020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 4.813319e+000 1.336768e+000 + vertex 1.482020e+001 2.659476e+000 3.500000e+000 + vertex 1.482020e+001 2.359533e+000 3.071637e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 4.150665e+000 6.093379e-001 + vertex 1.482020e+001 2.359533e+000 3.071637e+000 + vertex 1.482020e+001 1.989763e+000 2.701867e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 1.482020e+001 1.989763e+000 2.701867e+000 + vertex 1.482020e+001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 1.087460e+000 2.180922e+000 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 1.482020e+001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 1.087460e+000 2.180922e+000 + vertex 1.482020e+001 6.140000e-002 0.000000e+000 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 1.087460e+000 2.180922e+000 + vertex 1.482020e+001 5.823445e-001 2.045577e+000 + vertex 1.482020e+001 6.140000e-002 0.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 6.140000e-002 0.000000e+000 + vertex 1.482020e+001 5.823445e-001 2.045577e+000 + vertex 1.482020e+001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.595445e-001 2.045577e+000 + vertex 1.482020e+001 6.140000e-002 0.000000e+000 + vertex 1.482020e+001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.595445e-001 2.045577e+000 + vertex 1.482020e+001 -8.068409e-001 7.596123e-002 + vertex 1.482020e+001 6.140000e-002 0.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.595445e-001 2.045577e+000 + vertex 1.482020e+001 -9.646604e-001 2.180922e+000 + vertex 1.482020e+001 -8.068409e-001 7.596123e-002 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -8.068409e-001 7.596123e-002 + vertex 1.482020e+001 -9.646604e-001 2.180922e+000 + vertex 1.482020e+001 -1.648701e+000 3.015369e-001 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -1.648701e+000 3.015369e-001 + vertex 1.482020e+001 -9.646604e-001 2.180922e+000 + vertex 1.482020e+001 -1.438600e+000 2.401924e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -2.438600e+000 6.698730e-001 + vertex 1.482020e+001 -1.438600e+000 2.401924e+000 + vertex 1.482020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -3.152538e+000 1.169778e+000 + vertex 1.482020e+001 -1.866963e+000 2.701867e+000 + vertex 1.482020e+001 -2.236733e+000 3.071637e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -3.768822e+000 1.786062e+000 + vertex 1.482020e+001 -2.236733e+000 3.071637e+000 + vertex 1.482020e+001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -3.768822e+000 1.786062e+000 + vertex 1.482020e+001 -3.152538e+000 1.169778e+000 + vertex 1.482020e+001 -2.236733e+000 3.071637e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -2.236733e+000 3.071637e+000 + vertex 1.482020e+001 -2.536676e+000 3.500000e+000 + vertex 1.482020e+001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.268727e+000 2.500000e+000 + vertex 1.482020e+001 -2.536676e+000 3.500000e+000 + vertex 1.482020e+001 -4.637063e+000 3.289899e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.637063e+000 3.289899e+000 + vertex 1.482020e+001 -2.536676e+000 3.500000e+000 + vertex 1.482020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.862639e+000 4.131759e+000 + vertex 1.482020e+001 -2.757678e+000 3.973940e+000 + vertex 1.482020e+001 -2.893023e+000 4.479055e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.938600e+000 5.000000e+000 + vertex 1.482020e+001 -2.893023e+000 4.479055e+000 + vertex 1.482020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.862639e+000 5.868241e+000 + vertex 1.482020e+001 -4.938600e+000 5.000000e+000 + vertex 1.482020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + vertex 1.482020e+001 5.980711e+000 4.019309e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 5.980711e+000 4.019309e+000 + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + vertex 1.482020e+001 5.740815e+000 3.064995e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + vertex 1.482020e+001 4.985439e+000 5.868241e+000 + vertex 1.482020e+001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 2.561400e+000 9.330127e+000 + vertex 1.482020e+001 1.989763e+000 7.298133e+000 + vertex 1.482020e+001 3.275338e+000 8.830222e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 2.561400e+000 9.330127e+000 + vertex 1.482020e+001 1.771501e+000 9.698463e+000 + vertex 1.482020e+001 1.561400e+000 7.598076e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 1.771501e+000 9.698463e+000 + vertex 1.482020e+001 9.296409e-001 9.924039e+000 + vertex 1.482020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 6.140000e-002 1.000000e+001 + vertex 1.482020e+001 5.823445e-001 7.954423e+000 + vertex 1.482020e+001 9.296409e-001 9.924039e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -8.068409e-001 9.924039e+000 + vertex 1.482020e+001 6.140000e-002 8.000000e+000 + vertex 1.482020e+001 6.140000e-002 1.000000e+001 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -8.068409e-001 9.924039e+000 + vertex 1.482020e+001 -1.648701e+000 9.698463e+000 + vertex 1.482020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -1.648701e+000 9.698463e+000 + vertex 1.482020e+001 -2.438600e+000 9.330127e+000 + vertex 1.482020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -3.768822e+000 8.213938e+000 + vertex 1.482020e+001 -4.268727e+000 7.500000e+000 + vertex 1.482020e+001 -2.536676e+000 6.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.938600e+000 5.000000e+000 + vertex 1.482020e+001 -4.862639e+000 4.131759e+000 + vertex 1.482020e+001 -2.893023e+000 4.479055e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -4.862639e+000 4.131759e+000 + vertex 1.482020e+001 -4.637063e+000 3.289899e+000 + vertex 1.482020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -2.438600e+000 6.698730e-001 + vertex 1.482020e+001 -1.866963e+000 2.701867e+000 + vertex 1.482020e+001 -3.152538e+000 1.169778e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 -2.438600e+000 6.698730e-001 + vertex 1.482020e+001 -1.648701e+000 3.015369e-001 + vertex 1.482020e+001 -1.438600e+000 2.401924e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 1.482020e+001 4.150665e+000 6.093379e-001 + vertex 1.482020e+001 1.989763e+000 2.701867e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 4.150665e+000 6.093379e-001 + vertex 1.482020e+001 4.813319e+000 1.336768e+000 + vertex 1.482020e+001 2.359533e+000 3.071637e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 1.482020e+001 4.813319e+000 1.336768e+000 + vertex 1.482020e+001 5.348164e+000 2.162726e+000 + vertex 1.482020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.832020e+001 1.706140e+001 5.000000e+000 + vertex 3.837337e+001 1.766917e+001 5.000000e+000 + vertex 2.657020e+001 1.609249e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.706996e+001 1.574256e+001 5.000000e+000 + vertex 3.832020e+001 1.706140e+001 5.000000e+000 + vertex 2.657020e+001 1.609249e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.706996e+001 1.574256e+001 5.000000e+000 + vertex 3.837337e+001 1.645363e+001 5.000000e+000 + vertex 3.832020e+001 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.706996e+001 1.574256e+001 5.000000e+000 + vertex 2.750136e+001 1.531116e+001 5.000000e+000 + vertex 3.837337e+001 1.645363e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.837337e+001 1.645363e+001 5.000000e+000 + vertex 2.750136e+001 1.531116e+001 5.000000e+000 + vertex 3.853128e+001 1.586433e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.853128e+001 1.586433e+001 5.000000e+000 + vertex 2.750136e+001 1.531116e+001 5.000000e+000 + vertex 2.785129e+001 1.481140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.878911e+001 1.531140e+001 5.000000e+000 + vertex 2.785129e+001 1.481140e+001 5.000000e+000 + vertex 2.810912e+001 1.425847e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.913904e+001 1.481164e+001 5.000000e+000 + vertex 2.810912e+001 1.425847e+001 5.000000e+000 + vertex 2.826703e+001 1.366917e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.957044e+001 1.438024e+001 5.000000e+000 + vertex 2.826703e+001 1.366917e+001 5.000000e+000 + vertex 2.832020e+001 1.306140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.007020e+001 1.403031e+001 5.000000e+000 + vertex 2.832020e+001 1.306140e+001 5.000000e+000 + vertex 2.826703e+001 1.245363e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.062313e+001 1.377248e+001 5.000000e+000 + vertex 2.826703e+001 1.245363e+001 5.000000e+000 + vertex 2.810912e+001 1.186433e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.785129e+001 1.131140e+001 5.000000e+000 + vertex 4.062313e+001 1.377248e+001 5.000000e+000 + vertex 2.810912e+001 1.186433e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.785129e+001 1.131140e+001 5.000000e+000 + vertex 4.121243e+001 1.361457e+001 5.000000e+000 + vertex 4.062313e+001 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.785129e+001 1.131140e+001 5.000000e+000 + vertex 2.750136e+001 1.081164e+001 5.000000e+000 + vertex 4.121243e+001 1.361457e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.121243e+001 1.361457e+001 5.000000e+000 + vertex 2.750136e+001 1.081164e+001 5.000000e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.182020e+001 1.356140e+001 5.000000e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.242797e+001 1.361457e+001 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.301727e+001 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.242797e+001 1.361457e+001 5.000000e+000 + vertex 4.182020e+001 1.356140e+001 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.837337e+001 1.766917e+001 5.000000e+000 + vertex 3.853128e+001 1.825847e+001 5.000000e+000 + vertex 2.601727e+001 1.635032e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.657020e+001 1.609249e+001 5.000000e+000 + vertex 3.837337e+001 1.766917e+001 5.000000e+000 + vertex 2.601727e+001 1.635032e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.878911e+001 1.881140e+001 5.000000e+000 + vertex 2.601727e+001 1.635032e+001 5.000000e+000 + vertex 3.853128e+001 1.825847e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.878911e+001 1.881140e+001 5.000000e+000 + vertex 2.542797e+001 1.650823e+001 5.000000e+000 + vertex 2.601727e+001 1.635032e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.878911e+001 1.881140e+001 5.000000e+000 + vertex 3.913904e+001 1.931116e+001 5.000000e+000 + vertex 2.542797e+001 1.650823e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.542797e+001 1.650823e+001 5.000000e+000 + vertex 3.913904e+001 1.931116e+001 5.000000e+000 + vertex 3.957044e+001 1.974256e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.482020e+001 1.656140e+001 5.000000e+000 + vertex 3.957044e+001 1.974256e+001 5.000000e+000 + vertex 4.007020e+001 2.009249e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 9.570200e+000 2.009249e+001 5.000000e+000 + vertex 4.007020e+001 2.009249e+001 5.000000e+000 + vertex 9.017271e+000 2.035032e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 9.570200e+000 2.009249e+001 5.000000e+000 + vertex 2.482020e+001 1.656140e+001 5.000000e+000 + vertex 4.007020e+001 2.009249e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 9.570200e+000 2.009249e+001 5.000000e+000 + vertex 1.006996e+001 1.974256e+001 5.000000e+000 + vertex 2.482020e+001 1.656140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.482020e+001 1.656140e+001 5.000000e+000 + vertex 1.006996e+001 1.974256e+001 5.000000e+000 + vertex 2.421243e+001 1.650823e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.421243e+001 1.650823e+001 5.000000e+000 + vertex 1.006996e+001 1.974256e+001 5.000000e+000 + vertex 1.050136e+001 1.931116e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 1.085129e+001 1.881140e+001 5.000000e+000 + vertex 2.421243e+001 1.650823e+001 5.000000e+000 + vertex 1.050136e+001 1.931116e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 1.085129e+001 1.881140e+001 5.000000e+000 + vertex 2.362313e+001 1.635032e+001 5.000000e+000 + vertex 2.421243e+001 1.650823e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 1.085129e+001 1.881140e+001 5.000000e+000 + vertex 1.110912e+001 1.825847e+001 5.000000e+000 + vertex 2.362313e+001 1.635032e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.362313e+001 1.635032e+001 5.000000e+000 + vertex 1.110912e+001 1.825847e+001 5.000000e+000 + vertex 1.126703e+001 1.766917e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.307020e+001 1.609249e+001 5.000000e+000 + vertex 1.126703e+001 1.766917e+001 5.000000e+000 + vertex 1.132020e+001 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.257044e+001 1.574256e+001 5.000000e+000 + vertex 1.132020e+001 1.706140e+001 5.000000e+000 + vertex 1.126703e+001 1.645363e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.213904e+001 1.531116e+001 5.000000e+000 + vertex 1.126703e+001 1.645363e+001 5.000000e+000 + vertex 1.110912e+001 1.586433e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.178911e+001 1.481140e+001 5.000000e+000 + vertex 1.110912e+001 1.586433e+001 5.000000e+000 + vertex 1.085129e+001 1.531140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.153128e+001 1.425847e+001 5.000000e+000 + vertex 1.085129e+001 1.531140e+001 5.000000e+000 + vertex 1.050136e+001 1.481164e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.137337e+001 1.366917e+001 5.000000e+000 + vertex 1.050136e+001 1.481164e+001 5.000000e+000 + vertex 1.006996e+001 1.438024e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.132020e+001 1.306140e+001 5.000000e+000 + vertex 1.006996e+001 1.438024e+001 5.000000e+000 + vertex 9.570200e+000 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.137337e+001 1.245363e+001 5.000000e+000 + vertex 9.570200e+000 1.403031e+001 5.000000e+000 + vertex 9.017271e+000 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.153128e+001 1.186433e+001 5.000000e+000 + vertex 9.017271e+000 1.377248e+001 5.000000e+000 + vertex 2.178911e+001 1.131140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.153128e+001 1.186433e+001 5.000000e+000 + vertex 2.137337e+001 1.245363e+001 5.000000e+000 + vertex 9.017271e+000 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.007020e+001 2.009249e+001 5.000000e+000 + vertex 4.062313e+001 2.035032e+001 5.000000e+000 + vertex 9.017271e+000 2.035032e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 9.017271e+000 2.035032e+001 5.000000e+000 + vertex 4.062313e+001 2.035032e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 8.427969e+000 2.050823e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 7.820200e+000 2.056140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 8.427969e+000 2.050823e+001 5.000000e+000 + vertex 9.017271e+000 2.035032e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.121243e+001 2.050823e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.062313e+001 2.035032e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.121243e+001 2.050823e+001 5.000000e+000 + vertex 4.182020e+001 2.056140e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.182020e+001 2.056140e+001 5.000000e+000 + vertex 4.242797e+001 2.050823e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.301727e+001 2.035032e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.242797e+001 2.050823e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.301727e+001 2.035032e+001 5.000000e+000 + vertex 4.357020e+001 2.009249e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.357020e+001 2.009249e+001 5.000000e+000 + vertex 4.406996e+001 1.974256e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.450136e+001 1.931116e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.406996e+001 1.974256e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.450136e+001 1.931116e+001 5.000000e+000 + vertex 4.485129e+001 1.881140e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.485129e+001 1.881140e+001 5.000000e+000 + vertex 4.510912e+001 1.825847e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.526703e+001 1.766917e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.510912e+001 1.825847e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.526703e+001 1.766917e+001 5.000000e+000 + vertex 4.532020e+001 1.706140e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.532020e+001 1.706140e+001 5.000000e+000 + vertex 4.526703e+001 1.645363e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.526703e+001 1.645363e+001 5.000000e+000 + vertex 4.510912e+001 1.586433e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.485129e+001 1.531140e+001 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.510912e+001 1.586433e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.485129e+001 1.531140e+001 5.000000e+000 + vertex 4.450136e+001 1.481164e+001 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.450136e+001 1.481164e+001 5.000000e+000 + vertex 4.406996e+001 1.438024e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.357020e+001 1.403031e+001 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.406996e+001 1.438024e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.357020e+001 1.403031e+001 5.000000e+000 + vertex 4.301727e+001 1.377248e+001 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.121243e+001 1.361457e+001 5.000000e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 4.182020e+001 1.356140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.062313e+001 1.377248e+001 5.000000e+000 + vertex 4.007020e+001 1.403031e+001 5.000000e+000 + vertex 2.826703e+001 1.245363e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.957044e+001 1.438024e+001 5.000000e+000 + vertex 2.832020e+001 1.306140e+001 5.000000e+000 + vertex 4.007020e+001 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.957044e+001 1.438024e+001 5.000000e+000 + vertex 3.913904e+001 1.481164e+001 5.000000e+000 + vertex 2.826703e+001 1.366917e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.878911e+001 1.531140e+001 5.000000e+000 + vertex 2.810912e+001 1.425847e+001 5.000000e+000 + vertex 3.913904e+001 1.481164e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.878911e+001 1.531140e+001 5.000000e+000 + vertex 3.853128e+001 1.586433e+001 5.000000e+000 + vertex 2.785129e+001 1.481140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.137337e+001 1.366917e+001 5.000000e+000 + vertex 1.006996e+001 1.438024e+001 5.000000e+000 + vertex 2.132020e+001 1.306140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.137337e+001 1.366917e+001 5.000000e+000 + vertex 2.153128e+001 1.425847e+001 5.000000e+000 + vertex 1.050136e+001 1.481164e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.178911e+001 1.481140e+001 5.000000e+000 + vertex 1.085129e+001 1.531140e+001 5.000000e+000 + vertex 2.153128e+001 1.425847e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.213904e+001 1.531116e+001 5.000000e+000 + vertex 1.110912e+001 1.586433e+001 5.000000e+000 + vertex 2.178911e+001 1.481140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.213904e+001 1.531116e+001 5.000000e+000 + vertex 2.257044e+001 1.574256e+001 5.000000e+000 + vertex 1.126703e+001 1.645363e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.257044e+001 1.574256e+001 5.000000e+000 + vertex 2.307020e+001 1.609249e+001 5.000000e+000 + vertex 1.132020e+001 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.307020e+001 1.609249e+001 5.000000e+000 + vertex 2.362313e+001 1.635032e+001 5.000000e+000 + vertex 1.126703e+001 1.766917e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.482020e+001 1.656140e+001 5.000000e+000 + vertex 2.542797e+001 1.650823e+001 5.000000e+000 + vertex 3.957044e+001 1.974256e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.750136e+001 1.081164e+001 5.000000e+000 + vertex 2.706996e+001 1.038024e+001 5.000000e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 2.706996e+001 1.038024e+001 5.000000e+000 + vertex 2.657020e+001 1.003031e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.601727e+001 9.772476e+000 5.000000e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 2.657020e+001 1.003031e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.601727e+001 9.772476e+000 5.000000e+000 + vertex 2.542797e+001 9.614573e+000 5.000000e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 2.542797e+001 9.614573e+000 5.000000e+000 + vertex 2.482020e+001 9.561400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex 2.482020e+001 9.561400e+000 5.000000e+000 + vertex 2.421243e+001 9.614573e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.362313e+001 9.772476e+000 5.000000e+000 + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex 2.421243e+001 9.614573e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.362313e+001 9.772476e+000 5.000000e+000 + vertex 2.307020e+001 1.003031e+001 5.000000e+000 + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex 2.307020e+001 1.003031e+001 5.000000e+000 + vertex 2.257044e+001 1.038024e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.213904e+001 1.081164e+001 5.000000e+000 + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex 2.257044e+001 1.038024e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.213904e+001 1.081164e+001 5.000000e+000 + vertex 8.427969e+000 1.361457e+001 5.000000e+000 + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.213904e+001 1.081164e+001 5.000000e+000 + vertex 2.178911e+001 1.131140e+001 5.000000e+000 + vertex 8.427969e+000 1.361457e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 8.427969e+000 1.361457e+001 5.000000e+000 + vertex 2.178911e+001 1.131140e+001 5.000000e+000 + vertex 9.017271e+000 1.377248e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 2.132020e+001 1.306140e+001 5.000000e+000 + vertex 9.570200e+000 1.403031e+001 5.000000e+000 + vertex 2.137337e+001 1.245363e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.373373e+000 1.766917e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 4.320200e+000 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.373373e+000 1.766917e+001 5.000000e+000 + vertex 4.531276e+000 1.825847e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 4.531276e+000 1.825847e+001 5.000000e+000 + vertex 4.789111e+000 1.881140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 5.139044e+000 1.931116e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 4.789111e+000 1.881140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 5.139044e+000 1.931116e+001 5.000000e+000 + vertex 5.570443e+000 1.974256e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 5.570443e+000 1.974256e+001 5.000000e+000 + vertex 6.070200e+000 2.009249e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 6.623129e+000 2.035032e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 6.070200e+000 2.009249e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 6.623129e+000 2.035032e+001 5.000000e+000 + vertex 7.212431e+000 2.050823e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 7.212431e+000 2.050823e+001 5.000000e+000 + vertex 7.820200e+000 2.056140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 8.427969e+000 1.361457e+001 5.000000e+000 + vertex 7.820200e+000 1.356140e+001 5.000000e+000 + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex 7.820200e+000 1.356140e+001 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 7.212431e+000 1.361457e+001 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex 7.820200e+000 1.356140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 7.212431e+000 1.361457e+001 5.000000e+000 + vertex 6.623129e+000 1.377248e+001 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex 6.623129e+000 1.377248e+001 5.000000e+000 + vertex 6.070200e+000 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 5.570443e+000 1.438024e+001 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex 6.070200e+000 1.403031e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 5.570443e+000 1.438024e+001 5.000000e+000 + vertex 5.139044e+000 1.481164e+001 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex 5.139044e+000 1.481164e+001 5.000000e+000 + vertex 4.789111e+000 1.531140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.531276e+000 1.586433e+001 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex 4.789111e+000 1.531140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.531276e+000 1.586433e+001 5.000000e+000 + vertex 4.373373e+000 1.645363e+001 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex 4.373373e+000 1.645363e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 4.373373e+000 1.645363e+001 5.000000e+000 + vertex 4.320200e+000 1.706140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 1.482020e+001 6.061400e+000 5.000000e+000 + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 2.482020e+001 9.561400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 3.482020e+001 6.061400e+000 5.000000e+000 + vertex 3.482020e+001 5.061400e+000 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.526703e+001 1.645363e+001 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 4.062313e+001 2.035032e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 9.961947e-001 8.715574e-002 + outer loop + vertex 3.482020e+001 5.061400e+000 5.000000e+000 + vertex 3.482020e+001 4.985439e+000 5.868241e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 9.961947e-001 8.715574e-002 + outer loop + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 3.482020e+001 4.985439e+000 5.868241e+000 + vertex 4.982020e+001 4.985439e+000 5.868241e+000 + endloop + endfacet + facet normal 0.000000e+000 9.659258e-001 2.588190e-001 + outer loop + vertex 4.982020e+001 4.985439e+000 5.868241e+000 + vertex 3.482020e+001 4.985439e+000 5.868241e+000 + vertex 3.482020e+001 4.759863e+000 6.710101e+000 + endloop + endfacet + facet normal 0.000000e+000 9.063078e-001 4.226183e-001 + outer loop + vertex 4.982020e+001 4.759863e+000 6.710101e+000 + vertex 3.482020e+001 4.759863e+000 6.710101e+000 + vertex 3.482020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 8.191520e-001 5.735764e-001 + outer loop + vertex 4.982020e+001 4.391527e+000 7.500000e+000 + vertex 3.482020e+001 4.391527e+000 7.500000e+000 + vertex 3.482020e+001 3.891622e+000 8.213938e+000 + endloop + endfacet + facet normal 0.000000e+000 7.071068e-001 7.071068e-001 + outer loop + vertex 4.982020e+001 3.891622e+000 8.213938e+000 + vertex 3.482020e+001 3.891622e+000 8.213938e+000 + vertex 3.482020e+001 3.275338e+000 8.830222e+000 + endloop + endfacet + facet normal 0.000000e+000 5.735764e-001 8.191520e-001 + outer loop + vertex 4.982020e+001 3.275338e+000 8.830222e+000 + vertex 3.482020e+001 3.275338e+000 8.830222e+000 + vertex 3.482020e+001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal 0.000000e+000 4.226183e-001 9.063078e-001 + outer loop + vertex 4.982020e+001 2.561400e+000 9.330127e+000 + vertex 3.482020e+001 2.561400e+000 9.330127e+000 + vertex 3.482020e+001 1.771501e+000 9.698463e+000 + endloop + endfacet + facet normal 0.000000e+000 2.588190e-001 9.659258e-001 + outer loop + vertex 4.982020e+001 1.771501e+000 9.698463e+000 + vertex 3.482020e+001 1.771501e+000 9.698463e+000 + vertex 3.482020e+001 9.296409e-001 9.924039e+000 + endloop + endfacet + facet normal 0.000000e+000 8.715574e-002 9.961947e-001 + outer loop + vertex 4.982020e+001 9.296409e-001 9.924039e+000 + vertex 3.482020e+001 9.296409e-001 9.924039e+000 + vertex 3.482020e+001 6.140000e-002 1.000000e+001 + endloop + endfacet + facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 + outer loop + vertex 4.982020e+001 6.140000e-002 1.000000e+001 + vertex 3.482020e+001 6.140000e-002 1.000000e+001 + vertex 3.482020e+001 -8.068409e-001 9.924039e+000 + endloop + endfacet + facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 + outer loop + vertex 4.982020e+001 -8.068409e-001 9.924039e+000 + vertex 3.482020e+001 -8.068409e-001 9.924039e+000 + vertex 3.482020e+001 -1.648701e+000 9.698463e+000 + endloop + endfacet + facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 + outer loop + vertex 4.982020e+001 -1.648701e+000 9.698463e+000 + vertex 3.482020e+001 -1.648701e+000 9.698463e+000 + vertex 3.482020e+001 -2.438600e+000 9.330127e+000 + endloop + endfacet + facet normal 0.000000e+000 -5.735764e-001 8.191520e-001 + outer loop + vertex 4.982020e+001 -2.438600e+000 9.330127e+000 + vertex 3.482020e+001 -2.438600e+000 9.330127e+000 + vertex 3.482020e+001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 + outer loop + vertex 4.982020e+001 -3.152538e+000 8.830222e+000 + vertex 3.482020e+001 -3.152538e+000 8.830222e+000 + vertex 3.482020e+001 -3.768822e+000 8.213938e+000 + endloop + endfacet + facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 + outer loop + vertex 4.982020e+001 -3.768822e+000 8.213938e+000 + vertex 3.482020e+001 -3.768822e+000 8.213938e+000 + vertex 3.482020e+001 -4.268727e+000 7.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 + outer loop + vertex 4.982020e+001 -4.268727e+000 7.500000e+000 + vertex 3.482020e+001 -4.268727e+000 7.500000e+000 + vertex 3.482020e+001 -4.637063e+000 6.710101e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 + outer loop + vertex 4.982020e+001 -4.637063e+000 6.710101e+000 + vertex 3.482020e+001 -4.637063e+000 6.710101e+000 + vertex 3.482020e+001 -4.862639e+000 5.868241e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.961947e-001 8.715574e-002 + outer loop + vertex 4.982020e+001 -4.862639e+000 5.868241e+000 + vertex 3.482020e+001 -4.862639e+000 5.868241e+000 + vertex 3.482020e+001 -4.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002 + outer loop + vertex 4.982020e+001 -4.938600e+000 5.000000e+000 + vertex 3.482020e+001 -4.938600e+000 5.000000e+000 + vertex 3.482020e+001 -4.862639e+000 4.131759e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 + outer loop + vertex 4.982020e+001 -4.862639e+000 4.131759e+000 + vertex 3.482020e+001 -4.862639e+000 4.131759e+000 + vertex 3.482020e+001 -4.637063e+000 3.289899e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 + outer loop + vertex 4.982020e+001 -4.637063e+000 3.289899e+000 + vertex 3.482020e+001 -4.637063e+000 3.289899e+000 + vertex 3.482020e+001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001 + outer loop + vertex 4.982020e+001 -4.268727e+000 2.500000e+000 + vertex 3.482020e+001 -4.268727e+000 2.500000e+000 + vertex 3.482020e+001 -3.768822e+000 1.786062e+000 + endloop + endfacet + facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 + outer loop + vertex 4.982020e+001 -3.768822e+000 1.786062e+000 + vertex 3.482020e+001 -3.768822e+000 1.786062e+000 + vertex 3.482020e+001 -3.152538e+000 1.169778e+000 + endloop + endfacet + facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001 + outer loop + vertex 4.982020e+001 -3.152538e+000 1.169778e+000 + vertex 3.482020e+001 -3.152538e+000 1.169778e+000 + vertex 3.482020e+001 -2.438600e+000 6.698730e-001 + endloop + endfacet + facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001 + outer loop + vertex 4.982020e+001 -2.438600e+000 6.698730e-001 + vertex 3.482020e+001 -2.438600e+000 6.698730e-001 + vertex 3.482020e+001 -1.648701e+000 3.015369e-001 + endloop + endfacet + facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001 + outer loop + vertex 4.982020e+001 -1.648701e+000 3.015369e-001 + vertex 3.482020e+001 -1.648701e+000 3.015369e-001 + vertex 3.482020e+001 -8.068409e-001 7.596123e-002 + endloop + endfacet + facet normal 0.000000e+000 -8.715574e-002 -9.961947e-001 + outer loop + vertex 4.982020e+001 -8.068409e-001 7.596123e-002 + vertex 3.482020e+001 -8.068409e-001 7.596123e-002 + vertex 3.482020e+001 6.140000e-002 0.000000e+000 + endloop + endfacet + facet normal -5.124559e-017 -8.715574e-002 -9.961947e-001 + outer loop + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.982020e+001 -8.068409e-001 7.596123e-002 + vertex 3.482020e+001 6.140000e-002 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001 + outer loop + vertex 4.982020e+001 -8.068409e-001 7.596123e-002 + vertex 4.982020e+001 -1.648701e+000 3.015369e-001 + vertex 3.482020e+001 -8.068409e-001 7.596123e-002 + endloop + endfacet + facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001 + outer loop + vertex 4.982020e+001 -1.648701e+000 3.015369e-001 + vertex 4.982020e+001 -2.438600e+000 6.698730e-001 + vertex 3.482020e+001 -1.648701e+000 3.015369e-001 + endloop + endfacet + facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001 + outer loop + vertex 4.982020e+001 -2.438600e+000 6.698730e-001 + vertex 4.982020e+001 -3.152538e+000 1.169778e+000 + vertex 3.482020e+001 -2.438600e+000 6.698730e-001 + endloop + endfacet + facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 + outer loop + vertex 4.982020e+001 -3.152538e+000 1.169778e+000 + vertex 4.982020e+001 -3.768822e+000 1.786062e+000 + vertex 3.482020e+001 -3.152538e+000 1.169778e+000 + endloop + endfacet + facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001 + outer loop + vertex 4.982020e+001 -3.768822e+000 1.786062e+000 + vertex 4.982020e+001 -4.268727e+000 2.500000e+000 + vertex 3.482020e+001 -3.768822e+000 1.786062e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 + outer loop + vertex 4.982020e+001 -4.268727e+000 2.500000e+000 + vertex 4.982020e+001 -4.637063e+000 3.289899e+000 + vertex 3.482020e+001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 + outer loop + vertex 4.982020e+001 -4.637063e+000 3.289899e+000 + vertex 4.982020e+001 -4.862639e+000 4.131759e+000 + vertex 3.482020e+001 -4.637063e+000 3.289899e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002 + outer loop + vertex 4.982020e+001 -4.862639e+000 4.131759e+000 + vertex 4.982020e+001 -4.938600e+000 5.000000e+000 + vertex 3.482020e+001 -4.862639e+000 4.131759e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.961947e-001 8.715574e-002 + outer loop + vertex 4.982020e+001 -4.938600e+000 5.000000e+000 + vertex 4.982020e+001 -4.862639e+000 5.868241e+000 + vertex 3.482020e+001 -4.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 + outer loop + vertex 4.982020e+001 -4.862639e+000 5.868241e+000 + vertex 4.982020e+001 -4.637063e+000 6.710101e+000 + vertex 3.482020e+001 -4.862639e+000 5.868241e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 + outer loop + vertex 4.982020e+001 -4.637063e+000 6.710101e+000 + vertex 4.982020e+001 -4.268727e+000 7.500000e+000 + vertex 3.482020e+001 -4.637063e+000 6.710101e+000 + endloop + endfacet + facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 + outer loop + vertex 4.982020e+001 -4.268727e+000 7.500000e+000 + vertex 4.982020e+001 -3.768822e+000 8.213938e+000 + vertex 3.482020e+001 -4.268727e+000 7.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 + outer loop + vertex 4.982020e+001 -3.768822e+000 8.213938e+000 + vertex 4.982020e+001 -3.152538e+000 8.830222e+000 + vertex 3.482020e+001 -3.768822e+000 8.213938e+000 + endloop + endfacet + facet normal 0.000000e+000 -5.735764e-001 8.191520e-001 + outer loop + vertex 4.982020e+001 -3.152538e+000 8.830222e+000 + vertex 4.982020e+001 -2.438600e+000 9.330127e+000 + vertex 3.482020e+001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 + outer loop + vertex 4.982020e+001 -2.438600e+000 9.330127e+000 + vertex 4.982020e+001 -1.648701e+000 9.698463e+000 + vertex 3.482020e+001 -2.438600e+000 9.330127e+000 + endloop + endfacet + facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 + outer loop + vertex 4.982020e+001 -1.648701e+000 9.698463e+000 + vertex 4.982020e+001 -8.068409e-001 9.924039e+000 + vertex 3.482020e+001 -1.648701e+000 9.698463e+000 + endloop + endfacet + facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 + outer loop + vertex 4.982020e+001 -8.068409e-001 9.924039e+000 + vertex 4.982020e+001 6.140000e-002 1.000000e+001 + vertex 3.482020e+001 -8.068409e-001 9.924039e+000 + endloop + endfacet + facet normal 0.000000e+000 8.715574e-002 9.961947e-001 + outer loop + vertex 4.982020e+001 6.140000e-002 1.000000e+001 + vertex 4.982020e+001 9.296409e-001 9.924039e+000 + vertex 3.482020e+001 6.140000e-002 1.000000e+001 + endloop + endfacet + facet normal 0.000000e+000 2.588190e-001 9.659258e-001 + outer loop + vertex 4.982020e+001 9.296409e-001 9.924039e+000 + vertex 4.982020e+001 1.771501e+000 9.698463e+000 + vertex 3.482020e+001 9.296409e-001 9.924039e+000 + endloop + endfacet + facet normal 0.000000e+000 4.226183e-001 9.063078e-001 + outer loop + vertex 4.982020e+001 1.771501e+000 9.698463e+000 + vertex 4.982020e+001 2.561400e+000 9.330127e+000 + vertex 3.482020e+001 1.771501e+000 9.698463e+000 + endloop + endfacet + facet normal 0.000000e+000 5.735764e-001 8.191520e-001 + outer loop + vertex 4.982020e+001 2.561400e+000 9.330127e+000 + vertex 4.982020e+001 3.275338e+000 8.830222e+000 + vertex 3.482020e+001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal 0.000000e+000 7.071068e-001 7.071068e-001 + outer loop + vertex 4.982020e+001 3.275338e+000 8.830222e+000 + vertex 4.982020e+001 3.891622e+000 8.213938e+000 + vertex 3.482020e+001 3.275338e+000 8.830222e+000 + endloop + endfacet + facet normal 0.000000e+000 8.191520e-001 5.735764e-001 + outer loop + vertex 4.982020e+001 3.891622e+000 8.213938e+000 + vertex 4.982020e+001 4.391527e+000 7.500000e+000 + vertex 3.482020e+001 3.891622e+000 8.213938e+000 + endloop + endfacet + facet normal 0.000000e+000 9.063078e-001 4.226183e-001 + outer loop + vertex 4.982020e+001 4.391527e+000 7.500000e+000 + vertex 4.982020e+001 4.759863e+000 6.710101e+000 + vertex 3.482020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 9.659258e-001 2.588190e-001 + outer loop + vertex 4.982020e+001 4.759863e+000 6.710101e+000 + vertex 4.982020e+001 4.985439e+000 5.868241e+000 + vertex 3.482020e+001 4.759863e+000 6.710101e+000 + endloop + endfacet + facet normal 1.432567e-016 1.253334e-017 -1.000000e+000 + outer loop + vertex 4.428222e+001 1.749552e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.432020e+001 1.706140e+001 -8.881784e-016 + endloop + endfacet + facet normal 1.174024e-016 3.145787e-017 -1.000000e+000 + outer loop + vertex 4.428222e+001 1.749552e+001 -8.881784e-016 + vertex 4.416943e+001 1.791645e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal 9.887861e-017 4.610785e-017 -1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.416943e+001 1.791645e+001 -8.881784e-016 + vertex 4.398526e+001 1.831140e+001 -8.881784e-016 + endloop + endfacet + facet normal 8.409715e-017 5.888546e-017 -1.000000e+000 + outer loop + vertex 4.373531e+001 1.866837e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.398526e+001 1.831140e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.118001e-017 7.118001e-017 -1.000000e+000 + outer loop + vertex 4.373531e+001 1.866837e+001 -8.881784e-016 + vertex 4.342717e+001 1.897651e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal 5.888546e-017 8.409715e-017 -1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.342717e+001 1.897651e+001 -8.881784e-016 + vertex 4.307020e+001 1.922646e+001 -8.881784e-016 + endloop + endfacet + facet normal 4.610785e-017 9.887861e-017 -1.000000e+000 + outer loop + vertex 4.267525e+001 1.941063e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.307020e+001 1.922646e+001 -8.881784e-016 + endloop + endfacet + facet normal 3.145787e-017 1.174024e-016 -1.000000e+000 + outer loop + vertex 4.267525e+001 1.941063e+001 -8.881784e-016 + vertex 4.225432e+001 1.952342e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal 1.253334e-017 1.432567e-016 -1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.225432e+001 1.952342e+001 -8.881784e-016 + vertex 4.182020e+001 1.956140e+001 -8.881784e-016 + endloop + endfacet + facet normal -1.618835e-017 1.850337e-016 -1.000000e+000 + outer loop + vertex 4.138608e+001 1.952342e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.182020e+001 1.956140e+001 -8.881784e-016 + endloop + endfacet + facet normal -7.259975e-017 2.709460e-016 -1.000000e+000 + outer loop + vertex 4.138608e+001 1.952342e+001 -8.881784e-016 + vertex 4.096515e+001 1.941063e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 1.571783e-016 -1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.096515e+001 1.941063e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal -1.383491e-031 1.571783e-016 -1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 4.096515e+001 1.941063e+001 -8.881784e-016 + vertex 8.675250e+000 1.941063e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.259975e-017 2.709460e-016 -1.000000e+000 + outer loop + vertex 8.254320e+000 1.952342e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 8.675250e+000 1.941063e+001 -8.881784e-016 + endloop + endfacet + facet normal 1.618835e-017 1.850337e-016 -1.000000e+000 + outer loop + vertex 8.254320e+000 1.952342e+001 -8.881784e-016 + vertex 7.820200e+000 1.956140e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal -1.253334e-017 1.432567e-016 -1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 7.820200e+000 1.956140e+001 -8.881784e-016 + vertex 7.386080e+000 1.952342e+001 -8.881784e-016 + endloop + endfacet + facet normal -3.145787e-017 1.174024e-016 -1.000000e+000 + outer loop + vertex 6.965150e+000 1.941063e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 7.386080e+000 1.952342e+001 -8.881784e-016 + endloop + endfacet + facet normal -4.610785e-017 9.887861e-017 -1.000000e+000 + outer loop + vertex 6.965150e+000 1.941063e+001 -8.881784e-016 + vertex 6.570200e+000 1.922646e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal -5.888546e-017 8.409715e-017 -1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 6.570200e+000 1.922646e+001 -8.881784e-016 + vertex 6.213231e+000 1.897651e+001 -8.881784e-016 + endloop + endfacet + facet normal -7.118001e-017 7.118001e-017 -1.000000e+000 + outer loop + vertex 5.905089e+000 1.866837e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 6.213231e+000 1.897651e+001 -8.881784e-016 + endloop + endfacet + facet normal -8.409715e-017 5.888546e-017 -1.000000e+000 + outer loop + vertex 5.905089e+000 1.866837e+001 -8.881784e-016 + vertex 5.655136e+000 1.831140e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal -9.887861e-017 4.610785e-017 -1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 5.655136e+000 1.831140e+001 -8.881784e-016 + vertex 5.470968e+000 1.791645e+001 -8.881784e-016 + endloop + endfacet + facet normal -1.174024e-016 3.145787e-017 -1.000000e+000 + outer loop + vertex 5.358181e+000 1.749552e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 5.470968e+000 1.791645e+001 -8.881784e-016 + endloop + endfacet + facet normal -1.432567e-016 1.253334e-017 -1.000000e+000 + outer loop + vertex 5.358181e+000 1.749552e+001 -8.881784e-016 + vertex 5.320200e+000 1.706140e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal -1.850337e-016 -1.618835e-017 -1.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 5.320200e+000 1.706140e+001 -8.881784e-016 + vertex 5.358181e+000 1.662728e+001 -8.881784e-016 + endloop + endfacet + facet normal -2.709460e-016 -7.259975e-017 -1.000000e+000 + outer loop + vertex 5.470968e+000 1.620635e+001 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex 5.358181e+000 1.662728e+001 -8.881784e-016 + endloop + endfacet + facet normal -1.015055e-016 3.552714e-017 -1.000000e+000 + outer loop + vertex 5.470968e+000 1.620635e+001 -8.881784e-016 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 5.470968e+000 1.620635e+001 -8.881784e-016 + vertex 5.655136e+000 1.581140e+001 -8.881784e-016 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex 5.655136e+000 1.581140e+001 -8.881784e-016 + vertex 5.905089e+000 1.545443e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 6.213231e+000 1.514629e+001 -8.881784e-016 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex 5.905089e+000 1.545443e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 6.213231e+000 1.514629e+001 -8.881784e-016 + vertex 6.570200e+000 1.489634e+001 -8.881784e-016 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex 6.570200e+000 1.489634e+001 -8.881784e-016 + vertex 6.965150e+000 1.471217e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 7.386080e+000 1.459938e+001 -8.881784e-016 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex 6.965150e+000 1.471217e+001 -8.881784e-016 + endloop + endfacet + facet normal 6.691135e-017 -3.482212e-017 -1.000000e+000 + outer loop + vertex 7.386080e+000 1.459938e+001 -8.881784e-016 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal -7.350854e-018 -8.402064e-017 -1.000000e+000 + outer loop + vertex 7.386080e+000 1.459938e+001 -8.881784e-016 + vertex 7.820200e+000 1.456140e+001 -8.881784e-016 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal 6.587563e-018 -7.529618e-017 -1.000000e+000 + outer loop + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 7.820200e+000 1.456140e+001 -8.881784e-016 + vertex 8.254320e+000 1.459938e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.134736e-017 4.995796e-017 -1.000000e+000 + outer loop + vertex 2.290509e+001 1.145443e+001 0.000000e+000 + vertex 8.254320e+000 1.459938e+001 -8.881784e-016 + vertex 2.265514e+001 1.181140e+001 0.000000e+000 + endloop + endfacet + facet normal 4.990041e-017 -4.995282e-017 -1.000000e+000 + outer loop + vertex 2.290509e+001 1.145443e+001 0.000000e+000 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 8.254320e+000 1.459938e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 2.290509e+001 1.145443e+001 0.000000e+000 + vertex 2.321323e+001 1.114629e+001 0.000000e+000 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 2.321323e+001 1.114629e+001 0.000000e+000 + vertex 2.357020e+001 1.089634e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 2.396515e+001 1.071217e+001 0.000000e+000 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 2.357020e+001 1.089634e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 2.396515e+001 1.071217e+001 0.000000e+000 + vertex 2.438608e+001 1.059938e+001 0.000000e+000 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 2.438608e+001 1.059938e+001 0.000000e+000 + vertex 2.482020e+001 1.056140e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 2.482020e+001 1.056140e+001 0.000000e+000 + vertex 2.525432e+001 1.059938e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 2.567525e+001 1.071217e+001 0.000000e+000 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 2.525432e+001 1.059938e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 2.567525e+001 1.071217e+001 0.000000e+000 + vertex 2.607020e+001 1.089634e+001 0.000000e+000 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 2.607020e+001 1.089634e+001 0.000000e+000 + vertex 2.642717e+001 1.114629e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 2.673531e+001 1.145443e+001 0.000000e+000 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 2.642717e+001 1.114629e+001 0.000000e+000 + endloop + endfacet + facet normal -4.990041e-017 -4.995282e-017 -1.000000e+000 + outer loop + vertex 2.673531e+001 1.145443e+001 0.000000e+000 + vertex 4.138608e+001 1.459938e+001 -8.881784e-016 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal -7.134736e-017 4.995796e-017 -1.000000e+000 + outer loop + vertex 2.673531e+001 1.145443e+001 0.000000e+000 + vertex 2.698526e+001 1.181140e+001 0.000000e+000 + vertex 4.138608e+001 1.459938e+001 -8.881784e-016 + endloop + endfacet + facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000 + outer loop + vertex 4.138608e+001 1.459938e+001 -8.881784e-016 + vertex 2.698526e+001 1.181140e+001 0.000000e+000 + vertex 4.096515e+001 1.471217e+001 -8.881784e-016 + endloop + endfacet + facet normal -7.033831e-017 3.279929e-017 -1.000000e+000 + outer loop + vertex 4.096515e+001 1.471217e+001 -8.881784e-016 + vertex 2.698526e+001 1.181140e+001 0.000000e+000 + vertex 2.716943e+001 1.220635e+001 0.000000e+000 + endloop + endfacet + facet normal -7.004568e-017 1.876868e-017 -1.000000e+000 + outer loop + vertex 4.057020e+001 1.489634e+001 -8.881784e-016 + vertex 2.716943e+001 1.220635e+001 0.000000e+000 + vertex 2.728222e+001 1.262728e+001 0.000000e+000 + endloop + endfacet + facet normal -6.785445e-017 5.936495e-018 -1.000000e+000 + outer loop + vertex 2.732020e+001 1.306140e+001 0.000000e+000 + vertex 4.057020e+001 1.489634e+001 -8.881784e-016 + vertex 2.728222e+001 1.262728e+001 0.000000e+000 + endloop + endfacet + facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000 + outer loop + vertex 2.732020e+001 1.306140e+001 0.000000e+000 + vertex 4.021323e+001 1.514629e+001 -8.881784e-016 + vertex 4.057020e+001 1.489634e+001 -8.881784e-016 + endloop + endfacet + facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000 + outer loop + vertex 2.732020e+001 1.306140e+001 0.000000e+000 + vertex 2.728222e+001 1.349552e+001 0.000000e+000 + vertex 4.021323e+001 1.514629e+001 -8.881784e-016 + endloop + endfacet + facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000 + outer loop + vertex 4.021323e+001 1.514629e+001 -8.881784e-016 + vertex 2.728222e+001 1.349552e+001 0.000000e+000 + vertex 3.990509e+001 1.545443e+001 -8.881784e-016 + endloop + endfacet + facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000 + outer loop + vertex 3.990509e+001 1.545443e+001 -8.881784e-016 + vertex 2.728222e+001 1.349552e+001 0.000000e+000 + vertex 2.716943e+001 1.391645e+001 0.000000e+000 + endloop + endfacet + facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000 + outer loop + vertex 3.965514e+001 1.581140e+001 -8.881784e-016 + vertex 2.716943e+001 1.391645e+001 0.000000e+000 + vertex 2.698526e+001 1.431140e+001 0.000000e+000 + endloop + endfacet + facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000 + outer loop + vertex 3.947097e+001 1.620635e+001 -8.881784e-016 + vertex 2.698526e+001 1.431140e+001 0.000000e+000 + vertex 2.673531e+001 1.466837e+001 0.000000e+000 + endloop + endfacet + facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000 + outer loop + vertex 3.935818e+001 1.662728e+001 -8.881784e-016 + vertex 2.673531e+001 1.466837e+001 0.000000e+000 + vertex 2.642717e+001 1.497651e+001 0.000000e+000 + endloop + endfacet + facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000 + outer loop + vertex 3.932020e+001 1.706140e+001 -8.881784e-016 + vertex 2.642717e+001 1.497651e+001 0.000000e+000 + vertex 2.607020e+001 1.522646e+001 0.000000e+000 + endloop + endfacet + facet normal -7.004568e-017 1.876868e-017 -1.000000e+000 + outer loop + vertex 3.935818e+001 1.749552e+001 -8.881784e-016 + vertex 2.607020e+001 1.522646e+001 0.000000e+000 + vertex 3.947097e+001 1.791645e+001 -8.881784e-016 + endloop + endfacet + facet normal -6.785445e-017 5.936495e-018 -1.000000e+000 + outer loop + vertex 3.935818e+001 1.749552e+001 -8.881784e-016 + vertex 3.932020e+001 1.706140e+001 -8.881784e-016 + vertex 2.607020e+001 1.522646e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 4.096515e+001 1.941063e+001 -8.881784e-016 + vertex 4.057020e+001 1.922646e+001 -8.881784e-016 + vertex 8.675250e+000 1.941063e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 8.675250e+000 1.941063e+001 -8.881784e-016 + vertex 4.057020e+001 1.922646e+001 -8.881784e-016 + vertex 9.070200e+000 1.922646e+001 -8.881784e-016 + endloop + endfacet + facet normal 3.279817e-031 -2.423364e-016 -1.000000e+000 + outer loop + vertex 9.070200e+000 1.922646e+001 -8.881784e-016 + vertex 4.057020e+001 1.922646e+001 -8.881784e-016 + vertex 2.482020e+001 1.556140e+001 0.000000e+000 + endloop + endfacet + facet normal 1.631843e-017 -1.865205e-016 -1.000000e+000 + outer loop + vertex 9.427169e+000 1.897651e+001 -8.881784e-016 + vertex 2.482020e+001 1.556140e+001 0.000000e+000 + vertex 2.438608e+001 1.552342e+001 0.000000e+000 + endloop + endfacet + facet normal 7.134736e-017 4.995796e-017 -1.000000e+000 + outer loop + vertex 9.735311e+000 1.866837e+001 -8.881784e-016 + vertex 2.438608e+001 1.552342e+001 0.000000e+000 + vertex 9.985264e+000 1.831140e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.719385e-017 7.719385e-017 -1.000000e+000 + outer loop + vertex 9.735311e+000 1.866837e+001 -8.881784e-016 + vertex 9.427169e+000 1.897651e+001 -8.881784e-016 + vertex 2.438608e+001 1.552342e+001 0.000000e+000 + endloop + endfacet + facet normal -8.446175e-017 1.206239e-016 -1.000000e+000 + outer loop + vertex 4.021323e+001 1.897651e+001 -8.881784e-016 + vertex 2.482020e+001 1.556140e+001 0.000000e+000 + vertex 4.057020e+001 1.922646e+001 -8.881784e-016 + endloop + endfacet + facet normal -1.631843e-017 -1.865205e-016 -1.000000e+000 + outer loop + vertex 4.021323e+001 1.897651e+001 -8.881784e-016 + vertex 2.525432e+001 1.552342e+001 0.000000e+000 + vertex 2.482020e+001 1.556140e+001 0.000000e+000 + endloop + endfacet + facet normal -7.719385e-017 7.719385e-017 -1.000000e+000 + outer loop + vertex 4.021323e+001 1.897651e+001 -8.881784e-016 + vertex 3.990509e+001 1.866837e+001 -8.881784e-016 + vertex 2.525432e+001 1.552342e+001 0.000000e+000 + endloop + endfacet + facet normal -7.134736e-017 4.995796e-017 -1.000000e+000 + outer loop + vertex 2.525432e+001 1.552342e+001 0.000000e+000 + vertex 3.990509e+001 1.866837e+001 -8.881784e-016 + vertex 3.965514e+001 1.831140e+001 -8.881784e-016 + endloop + endfacet + facet normal -7.033831e-017 3.279929e-017 -1.000000e+000 + outer loop + vertex 2.567525e+001 1.541063e+001 0.000000e+000 + vertex 3.965514e+001 1.831140e+001 -8.881784e-016 + vertex 3.947097e+001 1.791645e+001 -8.881784e-016 + endloop + endfacet + facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000 + outer loop + vertex 2.607020e+001 1.522646e+001 0.000000e+000 + vertex 2.567525e+001 1.541063e+001 0.000000e+000 + vertex 3.947097e+001 1.791645e+001 -8.881784e-016 + endloop + endfacet + facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000 + outer loop + vertex 3.932020e+001 1.706140e+001 -8.881784e-016 + vertex 3.935818e+001 1.662728e+001 -8.881784e-016 + vertex 2.642717e+001 1.497651e+001 0.000000e+000 + endloop + endfacet + facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000 + outer loop + vertex 3.947097e+001 1.620635e+001 -8.881784e-016 + vertex 2.673531e+001 1.466837e+001 0.000000e+000 + vertex 3.935818e+001 1.662728e+001 -8.881784e-016 + endloop + endfacet + facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000 + outer loop + vertex 3.947097e+001 1.620635e+001 -8.881784e-016 + vertex 3.965514e+001 1.581140e+001 -8.881784e-016 + vertex 2.698526e+001 1.431140e+001 0.000000e+000 + endloop + endfacet + facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000 + outer loop + vertex 3.965514e+001 1.581140e+001 -8.881784e-016 + vertex 3.990509e+001 1.545443e+001 -8.881784e-016 + vertex 2.716943e+001 1.391645e+001 0.000000e+000 + endloop + endfacet + facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000 + outer loop + vertex 4.096515e+001 1.471217e+001 -8.881784e-016 + vertex 2.716943e+001 1.220635e+001 0.000000e+000 + vertex 4.057020e+001 1.489634e+001 -8.881784e-016 + endloop + endfacet + facet normal -6.587563e-018 -7.529618e-017 -1.000000e+000 + outer loop + vertex 4.182020e+001 1.456140e+001 -8.881784e-016 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 4.138608e+001 1.459938e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.350854e-018 -8.402064e-017 -1.000000e+000 + outer loop + vertex 4.182020e+001 1.456140e+001 -8.881784e-016 + vertex 4.225432e+001 1.459938e+001 -8.881784e-016 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + endloop + endfacet + facet normal -6.691135e-017 -3.482212e-017 -1.000000e+000 + outer loop + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 4.225432e+001 1.459938e+001 -8.881784e-016 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal -5.921189e-017 0.000000e+000 -1.000000e+000 + outer loop + vertex 3.482020e+001 6.140000e-002 0.000000e+000 + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 4.267525e+001 1.471217e+001 -8.881784e-016 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.225432e+001 1.459938e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 4.267525e+001 1.471217e+001 -8.881784e-016 + vertex 4.307020e+001 1.489634e+001 -8.881784e-016 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.307020e+001 1.489634e+001 -8.881784e-016 + vertex 4.342717e+001 1.514629e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 4.373531e+001 1.545443e+001 -8.881784e-016 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.342717e+001 1.514629e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 4.373531e+001 1.545443e+001 -8.881784e-016 + vertex 4.398526e+001 1.581140e+001 -8.881784e-016 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.398526e+001 1.581140e+001 -8.881784e-016 + vertex 4.416943e+001 1.620635e+001 -8.881784e-016 + endloop + endfacet + facet normal 2.709460e-016 -7.259975e-017 -1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.416943e+001 1.620635e+001 -8.881784e-016 + vertex 4.428222e+001 1.662728e+001 -8.881784e-016 + endloop + endfacet + facet normal 1.850337e-016 -1.618835e-017 -1.000000e+000 + outer loop + vertex 4.432020e+001 1.706140e+001 -8.881784e-016 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.428222e+001 1.662728e+001 -8.881784e-016 + endloop + endfacet + facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000 + outer loop + vertex 2.567525e+001 1.541063e+001 0.000000e+000 + vertex 2.525432e+001 1.552342e+001 0.000000e+000 + vertex 3.965514e+001 1.831140e+001 -8.881784e-016 + endloop + endfacet + facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000 + outer loop + vertex 2.438608e+001 1.552342e+001 0.000000e+000 + vertex 2.396515e+001 1.541063e+001 0.000000e+000 + vertex 9.985264e+000 1.831140e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.033831e-017 3.279929e-017 -1.000000e+000 + outer loop + vertex 9.985264e+000 1.831140e+001 -8.881784e-016 + vertex 2.396515e+001 1.541063e+001 0.000000e+000 + vertex 1.016943e+001 1.791645e+001 -8.881784e-016 + endloop + endfacet + facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000 + outer loop + vertex 1.016943e+001 1.791645e+001 -8.881784e-016 + vertex 2.396515e+001 1.541063e+001 0.000000e+000 + vertex 2.357020e+001 1.522646e+001 0.000000e+000 + endloop + endfacet + facet normal 6.785445e-017 5.936495e-018 -1.000000e+000 + outer loop + vertex 1.028222e+001 1.749552e+001 -8.881784e-016 + vertex 2.357020e+001 1.522646e+001 0.000000e+000 + vertex 1.032020e+001 1.706140e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.004568e-017 1.876868e-017 -1.000000e+000 + outer loop + vertex 1.028222e+001 1.749552e+001 -8.881784e-016 + vertex 1.016943e+001 1.791645e+001 -8.881784e-016 + vertex 2.357020e+001 1.522646e+001 0.000000e+000 + endloop + endfacet + facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000 + outer loop + vertex 2.357020e+001 1.522646e+001 0.000000e+000 + vertex 2.321323e+001 1.497651e+001 0.000000e+000 + vertex 1.032020e+001 1.706140e+001 -8.881784e-016 + endloop + endfacet + facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000 + outer loop + vertex 1.032020e+001 1.706140e+001 -8.881784e-016 + vertex 2.321323e+001 1.497651e+001 0.000000e+000 + vertex 1.028222e+001 1.662728e+001 -8.881784e-016 + endloop + endfacet + facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000 + outer loop + vertex 1.028222e+001 1.662728e+001 -8.881784e-016 + vertex 2.321323e+001 1.497651e+001 0.000000e+000 + vertex 2.290509e+001 1.466837e+001 0.000000e+000 + endloop + endfacet + facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000 + outer loop + vertex 1.016943e+001 1.620635e+001 -8.881784e-016 + vertex 2.290509e+001 1.466837e+001 0.000000e+000 + vertex 2.265514e+001 1.431140e+001 0.000000e+000 + endloop + endfacet + facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000 + outer loop + vertex 9.985264e+000 1.581140e+001 -8.881784e-016 + vertex 2.265514e+001 1.431140e+001 0.000000e+000 + vertex 2.247097e+001 1.391645e+001 0.000000e+000 + endloop + endfacet + facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000 + outer loop + vertex 9.735311e+000 1.545443e+001 -8.881784e-016 + vertex 2.247097e+001 1.391645e+001 0.000000e+000 + vertex 2.235818e+001 1.349552e+001 0.000000e+000 + endloop + endfacet + facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000 + outer loop + vertex 9.427169e+000 1.514629e+001 -8.881784e-016 + vertex 2.235818e+001 1.349552e+001 0.000000e+000 + vertex 2.232020e+001 1.306140e+001 0.000000e+000 + endloop + endfacet + facet normal 6.785445e-017 5.936495e-018 -1.000000e+000 + outer loop + vertex 9.070200e+000 1.489634e+001 -8.881784e-016 + vertex 2.232020e+001 1.306140e+001 0.000000e+000 + vertex 2.235818e+001 1.262728e+001 0.000000e+000 + endloop + endfacet + facet normal 7.004568e-017 1.876868e-017 -1.000000e+000 + outer loop + vertex 2.247097e+001 1.220635e+001 0.000000e+000 + vertex 9.070200e+000 1.489634e+001 -8.881784e-016 + vertex 2.235818e+001 1.262728e+001 0.000000e+000 + endloop + endfacet + facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000 + outer loop + vertex 2.247097e+001 1.220635e+001 0.000000e+000 + vertex 8.675250e+000 1.471217e+001 -8.881784e-016 + vertex 9.070200e+000 1.489634e+001 -8.881784e-016 + endloop + endfacet + facet normal 7.033831e-017 3.279929e-017 -1.000000e+000 + outer loop + vertex 2.247097e+001 1.220635e+001 0.000000e+000 + vertex 2.265514e+001 1.181140e+001 0.000000e+000 + vertex 8.675250e+000 1.471217e+001 -8.881784e-016 + endloop + endfacet + facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000 + outer loop + vertex 8.675250e+000 1.471217e+001 -8.881784e-016 + vertex 2.265514e+001 1.181140e+001 0.000000e+000 + vertex 8.254320e+000 1.459938e+001 -8.881784e-016 + endloop + endfacet + facet normal 8.446175e-017 1.206239e-016 -1.000000e+000 + outer loop + vertex 9.427169e+000 1.897651e+001 -8.881784e-016 + vertex 9.070200e+000 1.922646e+001 -8.881784e-016 + vertex 2.482020e+001 1.556140e+001 0.000000e+000 + endloop + endfacet + facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000 + outer loop + vertex 9.427169e+000 1.514629e+001 -8.881784e-016 + vertex 2.232020e+001 1.306140e+001 0.000000e+000 + vertex 9.070200e+000 1.489634e+001 -8.881784e-016 + endloop + endfacet + facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000 + outer loop + vertex 9.427169e+000 1.514629e+001 -8.881784e-016 + vertex 9.735311e+000 1.545443e+001 -8.881784e-016 + vertex 2.235818e+001 1.349552e+001 0.000000e+000 + endloop + endfacet + facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000 + outer loop + vertex 9.985264e+000 1.581140e+001 -8.881784e-016 + vertex 2.247097e+001 1.391645e+001 0.000000e+000 + vertex 9.735311e+000 1.545443e+001 -8.881784e-016 + endloop + endfacet + facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000 + outer loop + vertex 9.985264e+000 1.581140e+001 -8.881784e-016 + vertex 1.016943e+001 1.620635e+001 -8.881784e-016 + vertex 2.265514e+001 1.431140e+001 0.000000e+000 + endloop + endfacet + facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000 + outer loop + vertex 1.028222e+001 1.662728e+001 -8.881784e-016 + vertex 2.290509e+001 1.466837e+001 0.000000e+000 + vertex 1.016943e+001 1.620635e+001 -8.881784e-016 + endloop + endfacet + facet normal 5.921189e-017 0.000000e+000 -1.000000e+000 + outer loop + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 1.482020e+001 6.140000e-002 0.000000e+000 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 1.015055e-016 3.552714e-017 -1.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.416943e+001 1.620635e+001 -8.881784e-016 + endloop + endfacet + facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 + outer loop + vertex 3.482020e+001 3.378025e+000 0.000000e+000 + vertex 1.482020e+001 3.378025e+000 0.000000e+000 + vertex 2.482020e+001 1.056140e+001 0.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 1.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + endloop + endfacet + facet normal 0.000000e+000 1.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.938600e+000 5.000000e+000 + vertex -1.798000e-001 -2.893023e+000 4.479055e+000 + vertex -1.798000e-001 -4.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -4.862639e+000 5.868241e+000 + vertex -1.798000e-001 -2.938600e+000 5.000000e+000 + vertex -1.798000e-001 -4.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -4.862639e+000 5.868241e+000 + vertex -1.798000e-001 -2.893023e+000 5.520945e+000 + vertex -1.798000e-001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -4.862639e+000 5.868241e+000 + vertex -1.798000e-001 -4.637063e+000 6.710101e+000 + vertex -1.798000e-001 -2.893023e+000 5.520945e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.893023e+000 5.520945e+000 + vertex -1.798000e-001 -4.637063e+000 6.710101e+000 + vertex -1.798000e-001 -2.757678e+000 6.026060e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.757678e+000 6.026060e+000 + vertex -1.798000e-001 -4.637063e+000 6.710101e+000 + vertex -1.798000e-001 -4.268727e+000 7.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.536676e+000 6.500000e+000 + vertex -1.798000e-001 -4.268727e+000 7.500000e+000 + vertex -1.798000e-001 -3.768822e+000 8.213938e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.236733e+000 6.928363e+000 + vertex -1.798000e-001 -3.768822e+000 8.213938e+000 + vertex -1.798000e-001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -1.866963e+000 7.298133e+000 + vertex -1.798000e-001 -3.152538e+000 8.830222e+000 + vertex -1.798000e-001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -1.866963e+000 7.298133e+000 + vertex -1.798000e-001 -2.236733e+000 6.928363e+000 + vertex -1.798000e-001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.893023e+000 4.479055e+000 + vertex -1.798000e-001 -2.757678e+000 3.973940e+000 + vertex -1.798000e-001 -4.862639e+000 4.131759e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -4.938600e+000 5.000000e+000 + vertex -1.798000e-001 -2.893023e+000 4.479055e+000 + vertex -1.798000e-001 -4.862639e+000 4.131759e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.536676e+000 3.500000e+000 + vertex -1.798000e-001 -4.637063e+000 3.289899e+000 + vertex -1.798000e-001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.536676e+000 3.500000e+000 + vertex -1.798000e-001 -4.268727e+000 2.500000e+000 + vertex -1.798000e-001 -4.637063e+000 3.289899e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.536676e+000 3.500000e+000 + vertex -1.798000e-001 -2.236733e+000 3.071637e+000 + vertex -1.798000e-001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -4.268727e+000 2.500000e+000 + vertex -1.798000e-001 -2.236733e+000 3.071637e+000 + vertex -1.798000e-001 -3.768822e+000 1.786062e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -3.768822e+000 1.786062e+000 + vertex -1.798000e-001 -2.236733e+000 3.071637e+000 + vertex -1.798000e-001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -3.152538e+000 1.169778e+000 + vertex -1.798000e-001 -1.866963e+000 2.701867e+000 + vertex -1.798000e-001 -2.438600e+000 6.698730e-001 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -3.152538e+000 1.169778e+000 + vertex -1.798000e-001 -3.768822e+000 1.786062e+000 + vertex -1.798000e-001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -1.438600e+000 2.401924e+000 + vertex -1.798000e-001 -2.438600e+000 6.698730e-001 + vertex -1.798000e-001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -1.438600e+000 2.401924e+000 + vertex -1.798000e-001 -1.648701e+000 3.015369e-001 + vertex -1.798000e-001 -2.438600e+000 6.698730e-001 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -1.438600e+000 2.401924e+000 + vertex -1.798000e-001 -9.646604e-001 2.180922e+000 + vertex -1.798000e-001 -1.648701e+000 3.015369e-001 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -1.648701e+000 3.015369e-001 + vertex -1.798000e-001 -9.646604e-001 2.180922e+000 + vertex -1.798000e-001 -8.068409e-001 7.596123e-002 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -8.068409e-001 7.596123e-002 + vertex -1.798000e-001 -9.646604e-001 2.180922e+000 + vertex -1.798000e-001 -4.595445e-001 2.045577e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex -1.798000e-001 -4.595445e-001 2.045577e+000 + vertex -1.798000e-001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 5.823445e-001 2.045577e+000 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex -1.798000e-001 6.140000e-002 2.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 5.823445e-001 2.045577e+000 + vertex -1.798000e-001 1.087460e+000 2.180922e+000 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex -1.798000e-001 1.087460e+000 2.180922e+000 + vertex -1.798000e-001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 1.989763e+000 2.701867e+000 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex -1.798000e-001 1.561400e+000 2.401924e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 1.989763e+000 2.701867e+000 + vertex -1.798000e-001 2.359533e+000 3.071637e+000 + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex -1.798000e-001 2.359533e+000 3.071637e+000 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 -2.095500e-016 -1.548743e-015 + outer loop + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex -1.798000e-001 2.359533e+000 3.071637e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 1.776357e-016 0.000000e+000 + outer loop + vertex -1.798000e-001 2.506140e+001 5.000000e+000 + vertex -1.798000e-001 2.506140e+001 0.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 -2.628500e-015 1.840496e-015 + outer loop + vertex -1.798000e-001 2.359533e+000 3.071637e+000 + vertex -1.798000e-001 2.659476e+000 3.500000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 -2.086809e-015 9.730950e-016 + outer loop + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex -1.798000e-001 2.659476e+000 3.500000e+000 + vertex -1.798000e-001 2.880478e+000 3.973940e+000 + endloop + endfacet + facet normal -1.000000e+000 -1.863973e-015 4.994500e-016 + outer loop + vertex -1.798000e-001 3.015823e+000 4.479055e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex -1.798000e-001 2.880478e+000 3.973940e+000 + endloop + endfacet + facet normal -1.000000e+000 -1.776357e-015 1.554111e-016 + outer loop + vertex -1.798000e-001 3.015823e+000 4.479055e+000 + vertex -1.798000e-001 3.061400e+000 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 -1.776357e-015 -1.554111e-016 + outer loop + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex -1.798000e-001 3.061400e+000 5.000000e+000 + vertex -1.798000e-001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 4.985439e+000 5.868241e+000 + vertex -1.798000e-001 3.015823e+000 5.520945e+000 + vertex -1.798000e-001 2.880478e+000 6.026060e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 4.759863e+000 6.710101e+000 + vertex -1.798000e-001 2.880478e+000 6.026060e+000 + vertex -1.798000e-001 2.659476e+000 6.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 4.391527e+000 7.500000e+000 + vertex -1.798000e-001 2.659476e+000 6.500000e+000 + vertex -1.798000e-001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 3.891622e+000 8.213938e+000 + vertex -1.798000e-001 2.359533e+000 6.928363e+000 + vertex -1.798000e-001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 3.275338e+000 8.830222e+000 + vertex -1.798000e-001 1.989763e+000 7.298133e+000 + vertex -1.798000e-001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 3.275338e+000 8.830222e+000 + vertex -1.798000e-001 3.891622e+000 8.213938e+000 + vertex -1.798000e-001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 1.989763e+000 7.298133e+000 + vertex -1.798000e-001 1.561400e+000 7.598076e+000 + vertex -1.798000e-001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 2.561400e+000 9.330127e+000 + vertex -1.798000e-001 1.561400e+000 7.598076e+000 + vertex -1.798000e-001 1.771501e+000 9.698463e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 1.771501e+000 9.698463e+000 + vertex -1.798000e-001 1.561400e+000 7.598076e+000 + vertex -1.798000e-001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 9.296409e-001 9.924039e+000 + vertex -1.798000e-001 1.087460e+000 7.819078e+000 + vertex -1.798000e-001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 1.000000e+001 + vertex -1.798000e-001 5.823445e-001 7.954423e+000 + vertex -1.798000e-001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -8.068409e-001 9.924039e+000 + vertex -1.798000e-001 6.140000e-002 8.000000e+000 + vertex -1.798000e-001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -1.648701e+000 9.698463e+000 + vertex -1.798000e-001 -4.595445e-001 7.954423e+000 + vertex -1.798000e-001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.438600e+000 9.330127e+000 + vertex -1.798000e-001 -9.646604e-001 7.819078e+000 + vertex -1.798000e-001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -3.152538e+000 8.830222e+000 + vertex -1.798000e-001 -2.438600e+000 9.330127e+000 + vertex -1.798000e-001 -1.438600e+000 7.598076e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.536676e+000 6.500000e+000 + vertex -1.798000e-001 -3.768822e+000 8.213938e+000 + vertex -1.798000e-001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -4.268727e+000 7.500000e+000 + vertex -1.798000e-001 -2.536676e+000 6.500000e+000 + vertex -1.798000e-001 -2.757678e+000 6.026060e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex -1.798000e-001 -8.068409e-001 7.596123e-002 + vertex -1.798000e-001 -4.595445e-001 2.045577e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -4.637063e+000 3.289899e+000 + vertex -1.798000e-001 -4.862639e+000 4.131759e+000 + vertex -1.798000e-001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -2.438600e+000 9.330127e+000 + vertex -1.798000e-001 -1.648701e+000 9.698463e+000 + vertex -1.798000e-001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 -1.648701e+000 9.698463e+000 + vertex -1.798000e-001 -8.068409e-001 9.924039e+000 + vertex -1.798000e-001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 1.000000e+001 + vertex -1.798000e-001 6.140000e-002 8.000000e+000 + vertex -1.798000e-001 -8.068409e-001 9.924039e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 6.140000e-002 1.000000e+001 + vertex -1.798000e-001 9.296409e-001 9.924039e+000 + vertex -1.798000e-001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 9.296409e-001 9.924039e+000 + vertex -1.798000e-001 1.771501e+000 9.698463e+000 + vertex -1.798000e-001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 2.359533e+000 6.928363e+000 + vertex -1.798000e-001 3.891622e+000 8.213938e+000 + vertex -1.798000e-001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 4.391527e+000 7.500000e+000 + vertex -1.798000e-001 4.759863e+000 6.710101e+000 + vertex -1.798000e-001 2.659476e+000 6.500000e+000 + endloop + endfacet + facet normal -1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex -1.798000e-001 4.759863e+000 6.710101e+000 + vertex -1.798000e-001 4.985439e+000 5.868241e+000 + vertex -1.798000e-001 2.880478e+000 6.026060e+000 + endloop + endfacet + facet normal -1.000000e+000 -7.105427e-016 4.029688e-015 + outer loop + vertex -1.798000e-001 4.985439e+000 5.868241e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex -1.798000e-001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal -1.061532e-017 -8.715574e-002 -9.961947e-001 + outer loop + vertex 1.482020e+001 6.140000e-002 0.000000e+000 + vertex 1.482020e+001 -8.068409e-001 7.596123e-002 + vertex -1.798000e-001 -8.068409e-001 7.596123e-002 + endloop + endfacet + facet normal 5.124559e-017 -8.715574e-002 -9.961947e-001 + outer loop + vertex -1.798000e-001 6.140000e-002 -8.881784e-016 + vertex 1.482020e+001 6.140000e-002 0.000000e+000 + vertex -1.798000e-001 -8.068409e-001 7.596123e-002 + endloop + endfacet + facet normal 2.547676e-017 -2.588190e-001 -9.659258e-001 + outer loop + vertex 1.482020e+001 -8.068409e-001 7.596123e-002 + vertex 1.482020e+001 -1.648701e+000 3.015369e-001 + vertex -1.798000e-001 -1.648701e+000 3.015369e-001 + endloop + endfacet + facet normal -3.065033e-017 -2.588190e-001 -9.659258e-001 + outer loop + vertex -1.798000e-001 -8.068409e-001 7.596123e-002 + vertex 1.482020e+001 -8.068409e-001 7.596123e-002 + vertex -1.798000e-001 -1.648701e+000 3.015369e-001 + endloop + endfacet + facet normal 4.246127e-018 -4.226183e-001 -9.063078e-001 + outer loop + vertex 1.482020e+001 -1.648701e+000 3.015369e-001 + vertex 1.482020e+001 -2.438600e+000 6.698730e-001 + vertex -1.798000e-001 -2.438600e+000 6.698730e-001 + endloop + endfacet + facet normal 3.616145e-018 -4.226183e-001 -9.063078e-001 + outer loop + vertex -1.798000e-001 -1.648701e+000 3.015369e-001 + vertex 1.482020e+001 -1.648701e+000 3.015369e-001 + vertex -1.798000e-001 -2.438600e+000 6.698730e-001 + endloop + endfacet + facet normal 8.492254e-018 -5.735764e-001 -8.191520e-001 + outer loop + vertex 1.482020e+001 -2.438600e+000 6.698730e-001 + vertex 1.482020e+001 -3.152538e+000 1.169778e+000 + vertex -1.798000e-001 -3.152538e+000 1.169778e+000 + endloop + endfacet + facet normal -2.427694e-017 -5.735764e-001 -8.191520e-001 + outer loop + vertex -1.798000e-001 -2.438600e+000 6.698730e-001 + vertex 1.482020e+001 -2.438600e+000 6.698730e-001 + vertex -1.798000e-001 -3.152538e+000 1.169778e+000 + endloop + endfacet + facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 + outer loop + vertex 1.482020e+001 -3.152538e+000 1.169778e+000 + vertex 1.482020e+001 -3.768822e+000 1.786062e+000 + vertex -1.798000e-001 -3.768822e+000 1.786062e+000 + endloop + endfacet + facet normal -4.186913e-017 -7.071068e-001 -7.071068e-001 + outer loop + vertex -1.798000e-001 -3.152538e+000 1.169778e+000 + vertex 1.482020e+001 -3.152538e+000 1.169778e+000 + vertex -1.798000e-001 -3.768822e+000 1.786062e+000 + endloop + endfacet + facet normal 2.123063e-017 -8.191520e-001 -5.735764e-001 + outer loop + vertex 1.482020e+001 -3.768822e+000 1.786062e+000 + vertex 1.482020e+001 -4.268727e+000 2.500000e+000 + vertex -1.798000e-001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal -2.908199e-017 -8.191520e-001 -5.735764e-001 + outer loop + vertex -1.798000e-001 -3.768822e+000 1.786062e+000 + vertex 1.482020e+001 -3.768822e+000 1.786062e+000 + vertex -1.798000e-001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal -3.616145e-018 -9.063078e-001 -4.226183e-001 + outer loop + vertex 1.482020e+001 -4.268727e+000 2.500000e+000 + vertex 1.482020e+001 -4.637063e+000 3.289899e+000 + vertex -1.798000e-001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 + outer loop + vertex -1.798000e-001 -4.268727e+000 2.500000e+000 + vertex 1.482020e+001 -4.637063e+000 3.289899e+000 + vertex -1.798000e-001 -4.637063e+000 3.289899e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 + outer loop + vertex -1.798000e-001 -4.637063e+000 3.289899e+000 + vertex 1.482020e+001 -4.637063e+000 3.289899e+000 + vertex -1.798000e-001 -4.862639e+000 4.131759e+000 + endloop + endfacet + facet normal 6.130066e-017 -9.659258e-001 -2.588190e-001 + outer loop + vertex -1.798000e-001 -4.862639e+000 4.131759e+000 + vertex 1.482020e+001 -4.637063e+000 3.289899e+000 + vertex 1.482020e+001 -4.862639e+000 4.131759e+000 + endloop + endfacet + facet normal -2.802264e-017 -9.961947e-001 -8.715574e-002 + outer loop + vertex -1.798000e-001 -4.938600e+000 5.000000e+000 + vertex 1.482020e+001 -4.862639e+000 4.131759e+000 + vertex 1.482020e+001 -4.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 3.318329e-017 -9.961947e-001 8.715574e-002 + outer loop + vertex -1.798000e-001 -4.862639e+000 5.868241e+000 + vertex 1.482020e+001 -4.938600e+000 5.000000e+000 + vertex 1.482020e+001 -4.862639e+000 5.868241e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 + outer loop + vertex -1.798000e-001 -4.637063e+000 6.710101e+000 + vertex 1.482020e+001 -4.862639e+000 5.868241e+000 + vertex 1.482020e+001 -4.637063e+000 6.710101e+000 + endloop + endfacet + facet normal 7.232290e-018 -9.063078e-001 4.226183e-001 + outer loop + vertex -1.798000e-001 -4.268727e+000 7.500000e+000 + vertex 1.482020e+001 -4.637063e+000 6.710101e+000 + vertex 1.482020e+001 -4.268727e+000 7.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 + outer loop + vertex -1.798000e-001 -3.768822e+000 8.213938e+000 + vertex 1.482020e+001 -4.268727e+000 7.500000e+000 + vertex 1.482020e+001 -3.768822e+000 8.213938e+000 + endloop + endfacet + facet normal -2.172279e-030 -7.071068e-001 7.071068e-001 + outer loop + vertex -1.798000e-001 -3.152538e+000 8.830222e+000 + vertex 1.482020e+001 -3.768822e+000 8.213938e+000 + vertex 1.482020e+001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal 3.884310e-017 -5.735764e-001 8.191520e-001 + outer loop + vertex -1.798000e-001 -2.438600e+000 9.330127e+000 + vertex 1.482020e+001 -3.152538e+000 8.830222e+000 + vertex 1.482020e+001 -2.438600e+000 9.330127e+000 + endloop + endfacet + facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 + outer loop + vertex -1.798000e-001 -1.648701e+000 9.698463e+000 + vertex 1.482020e+001 -2.438600e+000 9.330127e+000 + vertex 1.482020e+001 -1.648701e+000 9.698463e+000 + endloop + endfacet + facet normal 8.428841e-017 -2.588190e-001 9.659258e-001 + outer loop + vertex -1.798000e-001 -8.068409e-001 9.924039e+000 + vertex 1.482020e+001 -1.648701e+000 9.698463e+000 + vertex 1.482020e+001 -8.068409e-001 9.924039e+000 + endloop + endfacet + facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 + outer loop + vertex -1.798000e-001 6.140000e-002 1.000000e+001 + vertex 1.482020e+001 -8.068409e-001 9.924039e+000 + vertex 1.482020e+001 6.140000e-002 1.000000e+001 + endloop + endfacet + facet normal -2.322295e-017 8.715574e-002 9.961947e-001 + outer loop + vertex -1.798000e-001 9.296409e-001 9.924039e+000 + vertex 1.482020e+001 6.140000e-002 1.000000e+001 + vertex 1.482020e+001 9.296409e-001 9.924039e+000 + endloop + endfacet + facet normal 4.159406e-017 2.588190e-001 9.659258e-001 + outer loop + vertex -1.798000e-001 1.771501e+000 9.698463e+000 + vertex 1.482020e+001 9.296409e-001 9.924039e+000 + vertex 1.482020e+001 1.771501e+000 9.698463e+000 + endloop + endfacet + facet normal 0.000000e+000 4.226183e-001 9.063078e-001 + outer loop + vertex -1.798000e-001 2.561400e+000 9.330127e+000 + vertex 1.482020e+001 1.771501e+000 9.698463e+000 + vertex 1.482020e+001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal 5.816399e-017 5.735764e-001 8.191520e-001 + outer loop + vertex -1.798000e-001 3.275338e+000 8.830222e+000 + vertex 1.482020e+001 2.561400e+000 9.330127e+000 + vertex 1.482020e+001 3.275338e+000 8.830222e+000 + endloop + endfacet + facet normal 0.000000e+000 7.071068e-001 7.071068e-001 + outer loop + vertex -1.798000e-001 3.891622e+000 8.213938e+000 + vertex 1.482020e+001 3.275338e+000 8.830222e+000 + vertex 1.482020e+001 3.891622e+000 8.213938e+000 + endloop + endfacet + facet normal 3.884310e-017 8.191520e-001 5.735764e-001 + outer loop + vertex -1.798000e-001 4.391527e+000 7.500000e+000 + vertex 1.482020e+001 3.891622e+000 8.213938e+000 + vertex 1.482020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 7.145594e-017 9.063078e-001 4.226183e-001 + outer loop + vertex -1.798000e-001 4.759863e+000 6.710101e+000 + vertex 1.482020e+001 4.391527e+000 7.500000e+000 + vertex 1.482020e+001 4.759863e+000 6.710101e+000 + endloop + endfacet + facet normal 0.000000e+000 9.659258e-001 2.588190e-001 + outer loop + vertex -1.798000e-001 4.985439e+000 5.868241e+000 + vertex 1.482020e+001 4.759863e+000 6.710101e+000 + vertex 1.482020e+001 4.985439e+000 5.868241e+000 + endloop + endfacet + facet normal 0.000000e+000 9.961947e-001 8.715574e-002 + outer loop + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + vertex -1.798000e-001 4.985439e+000 5.868241e+000 + vertex 1.482020e+001 4.985439e+000 5.868241e+000 + endloop + endfacet + facet normal 0.000000e+000 9.961947e-001 8.715574e-002 + outer loop + vertex 1.482020e+001 5.061400e+000 5.000000e+000 + vertex -1.798000e-001 5.061400e+000 5.000000e+000 + vertex -1.798000e-001 4.985439e+000 5.868241e+000 + endloop + endfacet + facet normal 1.910757e-017 9.659258e-001 2.588190e-001 + outer loop + vertex -1.798000e-001 4.985439e+000 5.868241e+000 + vertex -1.798000e-001 4.759863e+000 6.710101e+000 + vertex 1.482020e+001 4.759863e+000 6.710101e+000 + endloop + endfacet + facet normal -8.492254e-018 9.063078e-001 4.226183e-001 + outer loop + vertex -1.798000e-001 4.759863e+000 6.710101e+000 + vertex -1.798000e-001 4.391527e+000 7.500000e+000 + vertex 1.482020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 8.191520e-001 5.735764e-001 + outer loop + vertex -1.798000e-001 4.391527e+000 7.500000e+000 + vertex -1.798000e-001 3.891622e+000 8.213938e+000 + vertex 1.482020e+001 3.891622e+000 8.213938e+000 + endloop + endfacet + facet normal -4.344559e-030 7.071068e-001 7.071068e-001 + outer loop + vertex -1.798000e-001 3.275338e+000 8.830222e+000 + vertex 1.482020e+001 3.275338e+000 8.830222e+000 + vertex -1.798000e-001 3.891622e+000 8.213938e+000 + endloop + endfacet + facet normal 0.000000e+000 5.735764e-001 8.191520e-001 + outer loop + vertex -1.798000e-001 3.275338e+000 8.830222e+000 + vertex -1.798000e-001 2.561400e+000 9.330127e+000 + vertex 1.482020e+001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal -1.153573e-017 4.226183e-001 9.063078e-001 + outer loop + vertex -1.798000e-001 1.771501e+000 9.698463e+000 + vertex 1.482020e+001 1.771501e+000 9.698463e+000 + vertex -1.798000e-001 2.561400e+000 9.330127e+000 + endloop + endfacet + facet normal -6.793803e-017 2.588190e-001 9.659258e-001 + outer loop + vertex -1.798000e-001 1.771501e+000 9.698463e+000 + vertex -1.798000e-001 9.296409e-001 9.924039e+000 + vertex 1.482020e+001 9.296409e-001 9.924039e+000 + endloop + endfacet + facet normal 0.000000e+000 8.715574e-002 9.961947e-001 + outer loop + vertex -1.798000e-001 9.296409e-001 9.924039e+000 + vertex -1.798000e-001 6.140000e-002 1.000000e+001 + vertex 1.482020e+001 6.140000e-002 1.000000e+001 + endloop + endfacet + facet normal 2.866136e-017 -8.715574e-002 9.961947e-001 + outer loop + vertex -1.798000e-001 6.140000e-002 1.000000e+001 + vertex -1.798000e-001 -8.068409e-001 9.924039e+000 + vertex 1.482020e+001 -8.068409e-001 9.924039e+000 + endloop + endfacet + facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 + outer loop + vertex -1.798000e-001 -8.068409e-001 9.924039e+000 + vertex -1.798000e-001 -1.648701e+000 9.698463e+000 + vertex 1.482020e+001 -1.648701e+000 9.698463e+000 + endloop + endfacet + facet normal -8.492254e-018 -4.226183e-001 9.063078e-001 + outer loop + vertex -1.798000e-001 -1.648701e+000 9.698463e+000 + vertex -1.798000e-001 -2.438600e+000 9.330127e+000 + vertex 1.482020e+001 -2.438600e+000 9.330127e+000 + endloop + endfacet + facet normal -5.944578e-017 -5.735764e-001 8.191520e-001 + outer loop + vertex -1.798000e-001 -2.438600e+000 9.330127e+000 + vertex -1.798000e-001 -3.152538e+000 8.830222e+000 + vertex 1.482020e+001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 + outer loop + vertex -1.798000e-001 -3.152538e+000 8.830222e+000 + vertex -1.798000e-001 -3.768822e+000 8.213938e+000 + vertex 1.482020e+001 -3.768822e+000 8.213938e+000 + endloop + endfacet + facet normal -3.821514e-017 -8.191520e-001 5.735764e-001 + outer loop + vertex -1.798000e-001 -3.768822e+000 8.213938e+000 + vertex -1.798000e-001 -4.268727e+000 7.500000e+000 + vertex 1.482020e+001 -4.268727e+000 7.500000e+000 + endloop + endfacet + facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 + outer loop + vertex -1.798000e-001 -4.268727e+000 7.500000e+000 + vertex -1.798000e-001 -4.637063e+000 6.710101e+000 + vertex 1.482020e+001 -4.637063e+000 6.710101e+000 + endloop + endfacet + facet normal -1.910757e-017 -9.659258e-001 2.588190e-001 + outer loop + vertex -1.798000e-001 -4.637063e+000 6.710101e+000 + vertex -1.798000e-001 -4.862639e+000 5.868241e+000 + vertex 1.482020e+001 -4.862639e+000 5.868241e+000 + endloop + endfacet + facet normal -9.023020e-017 -9.961947e-001 8.715574e-002 + outer loop + vertex -1.798000e-001 -4.862639e+000 5.868241e+000 + vertex -1.798000e-001 -4.938600e+000 5.000000e+000 + vertex 1.482020e+001 -4.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 2.016910e-017 -9.961947e-001 -8.715574e-002 + outer loop + vertex -1.798000e-001 -4.938600e+000 5.000000e+000 + vertex -1.798000e-001 -4.862639e+000 4.131759e+000 + vertex 1.482020e+001 -4.862639e+000 4.131759e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -2.893023e+000 5.520945e+000 + vertex 4.982020e+001 -4.862639e+000 5.868241e+000 + vertex 4.982020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -2.893023e+000 5.520945e+000 + vertex 4.982020e+001 -4.637063e+000 6.710101e+000 + vertex 4.982020e+001 -4.862639e+000 5.868241e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -2.893023e+000 5.520945e+000 + vertex 4.982020e+001 -2.757678e+000 6.026060e+000 + vertex 4.982020e+001 -4.637063e+000 6.710101e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.637063e+000 6.710101e+000 + vertex 4.982020e+001 -2.757678e+000 6.026060e+000 + vertex 4.982020e+001 -4.268727e+000 7.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.268727e+000 7.500000e+000 + vertex 4.982020e+001 -2.757678e+000 6.026060e+000 + vertex 4.982020e+001 -2.536676e+000 6.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -3.768822e+000 8.213938e+000 + vertex 4.982020e+001 -2.536676e+000 6.500000e+000 + vertex 4.982020e+001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -1.866963e+000 7.298133e+000 + vertex 4.982020e+001 -3.768822e+000 8.213938e+000 + vertex 4.982020e+001 -2.236733e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -1.866963e+000 7.298133e+000 + vertex 4.982020e+001 -3.152538e+000 8.830222e+000 + vertex 4.982020e+001 -3.768822e+000 8.213938e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -1.866963e+000 7.298133e+000 + vertex 4.982020e+001 -1.438600e+000 7.598076e+000 + vertex 4.982020e+001 -3.152538e+000 8.830222e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -3.152538e+000 8.830222e+000 + vertex 4.982020e+001 -1.438600e+000 7.598076e+000 + vertex 4.982020e+001 -2.438600e+000 9.330127e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -2.438600e+000 9.330127e+000 + vertex 4.982020e+001 -1.438600e+000 7.598076e+000 + vertex 4.982020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -1.648701e+000 9.698463e+000 + vertex 4.982020e+001 -9.646604e-001 7.819078e+000 + vertex 4.982020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -8.068409e-001 9.924039e+000 + vertex 4.982020e+001 -4.595445e-001 7.954423e+000 + vertex 4.982020e+001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 6.140000e-002 1.000000e+001 + vertex 4.982020e+001 6.140000e-002 8.000000e+000 + vertex 4.982020e+001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 9.296409e-001 9.924039e+000 + vertex 4.982020e+001 5.823445e-001 7.954423e+000 + vertex 4.982020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 1.771501e+000 9.698463e+000 + vertex 4.982020e+001 1.087460e+000 7.819078e+000 + vertex 4.982020e+001 1.561400e+000 7.598076e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 2.561400e+000 9.330127e+000 + vertex 4.982020e+001 1.561400e+000 7.598076e+000 + vertex 4.982020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 3.275338e+000 8.830222e+000 + vertex 4.982020e+001 1.989763e+000 7.298133e+000 + vertex 4.982020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 3.891622e+000 8.213938e+000 + vertex 4.982020e+001 2.359533e+000 6.928363e+000 + vertex 4.982020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 3.891622e+000 8.213938e+000 + vertex 4.982020e+001 3.275338e+000 8.830222e+000 + vertex 4.982020e+001 2.359533e+000 6.928363e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 2.359533e+000 6.928363e+000 + vertex 4.982020e+001 2.659476e+000 6.500000e+000 + vertex 4.982020e+001 4.391527e+000 7.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 4.391527e+000 7.500000e+000 + vertex 4.982020e+001 2.659476e+000 6.500000e+000 + vertex 4.982020e+001 4.759863e+000 6.710101e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 4.759863e+000 6.710101e+000 + vertex 4.982020e+001 2.659476e+000 6.500000e+000 + vertex 4.982020e+001 2.880478e+000 6.026060e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 4.985439e+000 5.868241e+000 + vertex 4.982020e+001 2.880478e+000 6.026060e+000 + vertex 4.982020e+001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.982020e+001 3.015823e+000 5.520945e+000 + vertex 4.982020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 3.015823e+000 4.479055e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.982020e+001 3.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 3.015823e+000 4.479055e+000 + vertex 4.982020e+001 2.880478e+000 3.973940e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.982020e+001 2.880478e+000 3.973940e+000 + vertex 4.982020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 2.359533e+000 3.071637e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.982020e+001 2.659476e+000 3.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 2.359533e+000 3.071637e+000 + vertex 4.982020e+001 1.989763e+000 2.701867e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.982020e+001 1.989763e+000 2.701867e+000 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 5.000000e+000 + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 1.989763e+000 2.701867e+000 + vertex 4.982020e+001 1.561400e+000 2.401924e+000 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 2.506140e+001 0.000000e+000 + vertex 4.982020e+001 1.989763e+000 2.701867e+000 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 1.561400e+000 2.401924e+000 + vertex 4.982020e+001 1.087460e+000 2.180922e+000 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.982020e+001 1.087460e+000 2.180922e+000 + vertex 4.982020e+001 5.823445e-001 2.045577e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 6.140000e-002 2.000000e+000 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.982020e+001 5.823445e-001 2.045577e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 6.140000e-002 2.000000e+000 + vertex 4.982020e+001 -4.595445e-001 2.045577e+000 + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 6.140000e-002 -8.881784e-016 + vertex 4.982020e+001 -4.595445e-001 2.045577e+000 + vertex 4.982020e+001 -8.068409e-001 7.596123e-002 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -8.068409e-001 7.596123e-002 + vertex 4.982020e+001 -4.595445e-001 2.045577e+000 + vertex 4.982020e+001 -9.646604e-001 2.180922e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -1.648701e+000 3.015369e-001 + vertex 4.982020e+001 -9.646604e-001 2.180922e+000 + vertex 4.982020e+001 -1.438600e+000 2.401924e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -2.438600e+000 6.698730e-001 + vertex 4.982020e+001 -1.438600e+000 2.401924e+000 + vertex 4.982020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -3.152538e+000 1.169778e+000 + vertex 4.982020e+001 -1.866963e+000 2.701867e+000 + vertex 4.982020e+001 -3.768822e+000 1.786062e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -3.152538e+000 1.169778e+000 + vertex 4.982020e+001 -2.438600e+000 6.698730e-001 + vertex 4.982020e+001 -1.866963e+000 2.701867e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -1.866963e+000 2.701867e+000 + vertex 4.982020e+001 -2.236733e+000 3.071637e+000 + vertex 4.982020e+001 -3.768822e+000 1.786062e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -3.768822e+000 1.786062e+000 + vertex 4.982020e+001 -2.236733e+000 3.071637e+000 + vertex 4.982020e+001 -4.268727e+000 2.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.268727e+000 2.500000e+000 + vertex 4.982020e+001 -2.236733e+000 3.071637e+000 + vertex 4.982020e+001 -2.536676e+000 3.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.637063e+000 3.289899e+000 + vertex 4.982020e+001 -2.536676e+000 3.500000e+000 + vertex 4.982020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.862639e+000 4.131759e+000 + vertex 4.982020e+001 -2.757678e+000 3.973940e+000 + vertex 4.982020e+001 -2.893023e+000 4.479055e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.938600e+000 5.000000e+000 + vertex 4.982020e+001 -2.893023e+000 4.479055e+000 + vertex 4.982020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.862639e+000 5.868241e+000 + vertex 4.982020e+001 -4.938600e+000 5.000000e+000 + vertex 4.982020e+001 -2.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 5.061400e+000 5.000000e+000 + vertex 4.982020e+001 4.985439e+000 5.868241e+000 + vertex 4.982020e+001 3.015823e+000 5.520945e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 4.759863e+000 6.710101e+000 + vertex 4.982020e+001 2.880478e+000 6.026060e+000 + vertex 4.982020e+001 4.985439e+000 5.868241e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 3.275338e+000 8.830222e+000 + vertex 4.982020e+001 2.561400e+000 9.330127e+000 + vertex 4.982020e+001 1.989763e+000 7.298133e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 2.561400e+000 9.330127e+000 + vertex 4.982020e+001 1.771501e+000 9.698463e+000 + vertex 4.982020e+001 1.561400e+000 7.598076e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 1.771501e+000 9.698463e+000 + vertex 4.982020e+001 9.296409e-001 9.924039e+000 + vertex 4.982020e+001 1.087460e+000 7.819078e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 9.296409e-001 9.924039e+000 + vertex 4.982020e+001 6.140000e-002 1.000000e+001 + vertex 4.982020e+001 5.823445e-001 7.954423e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 6.140000e-002 1.000000e+001 + vertex 4.982020e+001 -8.068409e-001 9.924039e+000 + vertex 4.982020e+001 6.140000e-002 8.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -8.068409e-001 9.924039e+000 + vertex 4.982020e+001 -1.648701e+000 9.698463e+000 + vertex 4.982020e+001 -4.595445e-001 7.954423e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -1.648701e+000 9.698463e+000 + vertex 4.982020e+001 -2.438600e+000 9.330127e+000 + vertex 4.982020e+001 -9.646604e-001 7.819078e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -3.768822e+000 8.213938e+000 + vertex 4.982020e+001 -4.268727e+000 7.500000e+000 + vertex 4.982020e+001 -2.536676e+000 6.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.862639e+000 4.131759e+000 + vertex 4.982020e+001 -2.893023e+000 4.479055e+000 + vertex 4.982020e+001 -4.938600e+000 5.000000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.862639e+000 4.131759e+000 + vertex 4.982020e+001 -4.637063e+000 3.289899e+000 + vertex 4.982020e+001 -2.757678e+000 3.973940e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -4.637063e+000 3.289899e+000 + vertex 4.982020e+001 -4.268727e+000 2.500000e+000 + vertex 4.982020e+001 -2.536676e+000 3.500000e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -2.438600e+000 6.698730e-001 + vertex 4.982020e+001 -1.648701e+000 3.015369e-001 + vertex 4.982020e+001 -1.438600e+000 2.401924e+000 + endloop + endfacet + facet normal 1.000000e+000 0.000000e+000 0.000000e+000 + outer loop + vertex 4.982020e+001 -8.068409e-001 7.596123e-002 + vertex 4.982020e+001 -9.646604e-001 2.180922e+000 + vertex 4.982020e+001 -1.648701e+000 3.015369e-001 + endloop + endfacet +endsolid From 4570812a0676d5d46a8ebe94c7b003680d653a8d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 4 Jul 2023 16:30:11 +0330 Subject: [PATCH 529/775] Cube as simple 3D structure for FEA --- files/cube.stl | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 files/cube.stl diff --git a/files/cube.stl b/files/cube.stl new file mode 100644 index 000000000..eabbe9e26 --- /dev/null +++ b/files/cube.stl @@ -0,0 +1,86 @@ +solid mesh +facet normal -1.0 0.0 0.0 + outer loop + vertex -10.0 -1.0 -1.0 + vertex -10.0 -1.0 1.0 + vertex -10.0 1.0 1.0 + endloop +endfacet +facet normal -1.0 0.0 -0.0 + outer loop + vertex -10.0 1.0 1.0 + vertex -10.0 1.0 -1.0 + vertex -10.0 -1.0 -1.0 + endloop +endfacet +facet normal 0.0 1.0 0.0 + outer loop + vertex -10.0 1.0 -1.0 + vertex -10.0 1.0 1.0 + vertex 10.0 1.0 1.0 + endloop +endfacet +facet normal 0.0 1.0 0.0 + outer loop + vertex 10.0 1.0 1.0 + vertex 10.0 1.0 -1.0 + vertex -10.0 1.0 -1.0 + endloop +endfacet +facet normal 1.0 0.0 -0.0 + outer loop + vertex 10.0 1.0 -1.0 + vertex 10.0 1.0 1.0 + vertex 10.0 -1.0 1.0 + endloop +endfacet +facet normal 1.0 0.0 0.0 + outer loop + vertex 10.0 -1.0 1.0 + vertex 10.0 -1.0 -1.0 + vertex 10.0 1.0 -1.0 + endloop +endfacet +facet normal 0.0 -1.0 0.0 + outer loop + vertex -10.0 -1.0 1.0 + vertex -10.0 -1.0 -1.0 + vertex 10.0 -1.0 -1.0 + endloop +endfacet +facet normal 0.0 -1.0 0.0 + outer loop + vertex 10.0 -1.0 -1.0 + vertex 10.0 -1.0 1.0 + vertex -10.0 -1.0 1.0 + endloop +endfacet +facet normal 0.0 0.0 1.0 + outer loop + vertex -10.0 -1.0 1.0 + vertex 10.0 -1.0 1.0 + vertex 10.0 1.0 1.0 + endloop +endfacet +facet normal 0.0 0.0 1.0 + outer loop + vertex 10.0 1.0 1.0 + vertex -10.0 1.0 1.0 + vertex -10.0 -1.0 1.0 + endloop +endfacet +facet normal 0.0 0.0 -1.0 + outer loop + vertex -10.0 -1.0 -1.0 + vertex -10.0 1.0 -1.0 + vertex 10.0 1.0 -1.0 + endloop +endfacet +facet normal 0.0 -0.0 -1.0 + outer loop + vertex 10.0 1.0 -1.0 + vertex 10.0 -1.0 -1.0 + vertex -10.0 -1.0 -1.0 + endloop +endfacet +endsolid mesh From 6ea6b082bea8daf4ba836b792023411e1f177f0f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 5 Jul 2023 12:46:43 +0330 Subject: [PATCH 530/775] Python code to generate cylinder --- files/generate_cylinder.py | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 files/generate_cylinder.py diff --git a/files/generate_cylinder.py b/files/generate_cylinder.py new file mode 100644 index 000000000..51abe9e9b --- /dev/null +++ b/files/generate_cylinder.py @@ -0,0 +1,60 @@ +import math + +def generate_cylinder_stl(radius, length, num_triangles, output_file): + with open(output_file, 'w') as stl_file: + stl_file.write("solid cylinder\n") + + angle_step = 2 * math.pi / num_triangles + + for i in range(num_triangles): + angle1 = i * angle_step + angle2 = (i + 1) * angle_step + + y1, z1 = radius * math.cos(angle1), radius * math.sin(angle1) + y2, z2 = radius * math.cos(angle2), radius * math.sin(angle2) + + # Base triangle + stl_file.write("facet normal -1.0 0.0 0.0\n") + stl_file.write("outer loop\n") + stl_file.write(f"vertex 0.0 0.0 0.0\n") + stl_file.write(f"vertex 0.0 {y2} {z2}\n") + stl_file.write(f"vertex 0.0 {y1} {z1}\n") + stl_file.write("endloop\n") + stl_file.write("endfacet\n") + + # Top triangle + stl_file.write("facet normal 1.0 0.0 0.0\n") + stl_file.write("outer loop\n") + stl_file.write(f"vertex {length} 0.0 0.0\n") + stl_file.write(f"vertex {length} {y1} {z1}\n") + stl_file.write(f"vertex {length} {y2} {z2}\n") + stl_file.write("endloop\n") + stl_file.write("endfacet\n") + + # Side triangles + normal = f"0.0 {math.cos(angle1)} {math.sin(angle1)}" + stl_file.write(f"facet normal {normal}\n") + stl_file.write("outer loop\n") + stl_file.write(f"vertex 0.0 {y1} {z1}\n") + stl_file.write(f"vertex 0.0 {y2} {z2}\n") + stl_file.write(f"vertex {length} {y1} {z1}\n") + stl_file.write("endloop\n") + stl_file.write("endfacet\n") + + normal = f"0.0 {math.cos(angle2)} {math.sin(angle2)}" + stl_file.write(f"facet normal {normal}\n") + stl_file.write("outer loop\n") + stl_file.write(f"vertex 0.0 {y2} {z2}\n") + stl_file.write(f"vertex {length} {y2} {z2}\n") + stl_file.write(f"vertex {length} {y1} {z1}\n") + stl_file.write("endloop\n") + stl_file.write("endfacet\n") + + stl_file.write("endsolid cylinder\n") + + +output_filename = "cylinder.stl" +radius = 12 +length = 100 +num_triangles = 36 +generate_cylinder_stl(radius, length, num_triangles,output_filename) From 27907ecab6049c4925f4984e18274ba09213547c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 5 Jul 2023 13:01:15 +0330 Subject: [PATCH 531/775] Shift cylinder along Z axis to be above XY plane --- files/generate_cylinder.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/files/generate_cylinder.py b/files/generate_cylinder.py index 51abe9e9b..28abe72ee 100644 --- a/files/generate_cylinder.py +++ b/files/generate_cylinder.py @@ -1,5 +1,6 @@ import math +# Cylinder is shifted by {+radius} along the Z axis to be above the XY plane. def generate_cylinder_stl(radius, length, num_triangles, output_file): with open(output_file, 'w') as stl_file: stl_file.write("solid cylinder\n") @@ -16,18 +17,18 @@ def generate_cylinder_stl(radius, length, num_triangles, output_file): # Base triangle stl_file.write("facet normal -1.0 0.0 0.0\n") stl_file.write("outer loop\n") - stl_file.write(f"vertex 0.0 0.0 0.0\n") - stl_file.write(f"vertex 0.0 {y2} {z2}\n") - stl_file.write(f"vertex 0.0 {y1} {z1}\n") + stl_file.write(f"vertex 0.0 0.0 {0.0+radius}\n") + stl_file.write(f"vertex 0.0 {y2} {z2+radius}\n") + stl_file.write(f"vertex 0.0 {y1} {z1+radius}\n") stl_file.write("endloop\n") stl_file.write("endfacet\n") # Top triangle stl_file.write("facet normal 1.0 0.0 0.0\n") stl_file.write("outer loop\n") - stl_file.write(f"vertex {length} 0.0 0.0\n") - stl_file.write(f"vertex {length} {y1} {z1}\n") - stl_file.write(f"vertex {length} {y2} {z2}\n") + stl_file.write(f"vertex {length} 0.0 {0.0+radius}\n") + stl_file.write(f"vertex {length} {y1} {z1+radius}\n") + stl_file.write(f"vertex {length} {y2} {z2+radius}\n") stl_file.write("endloop\n") stl_file.write("endfacet\n") @@ -35,18 +36,18 @@ def generate_cylinder_stl(radius, length, num_triangles, output_file): normal = f"0.0 {math.cos(angle1)} {math.sin(angle1)}" stl_file.write(f"facet normal {normal}\n") stl_file.write("outer loop\n") - stl_file.write(f"vertex 0.0 {y1} {z1}\n") - stl_file.write(f"vertex 0.0 {y2} {z2}\n") - stl_file.write(f"vertex {length} {y1} {z1}\n") + stl_file.write(f"vertex 0.0 {y1} {z1+radius}\n") + stl_file.write(f"vertex 0.0 {y2} {z2+radius}\n") + stl_file.write(f"vertex {length} {y1} {z1+radius}\n") stl_file.write("endloop\n") stl_file.write("endfacet\n") normal = f"0.0 {math.cos(angle2)} {math.sin(angle2)}" stl_file.write(f"facet normal {normal}\n") stl_file.write("outer loop\n") - stl_file.write(f"vertex 0.0 {y2} {z2}\n") - stl_file.write(f"vertex {length} {y2} {z2}\n") - stl_file.write(f"vertex {length} {y1} {z1}\n") + stl_file.write(f"vertex 0.0 {y2} {z2+radius}\n") + stl_file.write(f"vertex {length} {y2} {z2+radius}\n") + stl_file.write(f"vertex {length} {y1} {z1+radius}\n") stl_file.write("endloop\n") stl_file.write("endfacet\n") From a1a7346d3e7a309eb5c5a0cac8b6756538264560 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 5 Jul 2023 14:12:23 +0330 Subject: [PATCH 532/775] Python script to generate cube STL --- files/generate_cube.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 files/generate_cube.py diff --git a/files/generate_cube.py b/files/generate_cube.py new file mode 100644 index 000000000..a7dd62163 --- /dev/null +++ b/files/generate_cube.py @@ -0,0 +1,35 @@ +def write_stl(filename): + with open(filename, 'w') as f: + f.write("solid cube\n") + for face in faces: + f.write(" facet normal 0 0 0\n") + f.write(" outer loop\n") + for vertex in face: + f.write(" vertex {} {} {}\n".format(*vertex)) + f.write(" endloop\n") + f.write(" endfacet\n") + f.write("endsolid cube") + +width = 12 +height = 22 +length = 100 + +# Define the 8 vertices of the cube +vertices = [(0, 0, 0), (length, 0, 0), (length, width, 0), (0, width, 0), + (0, 0, height), (length, 0, height), (length, width, height), (0, width, height)] + +# Define the 12 triangles composing the cube +faces = [(vertices[0], vertices[1], vertices[2]), + (vertices[0], vertices[2], vertices[3]), + (vertices[0], vertices[1], vertices[5]), + (vertices[0], vertices[5], vertices[4]), + (vertices[1], vertices[2], vertices[6]), + (vertices[1], vertices[6], vertices[5]), + (vertices[2], vertices[3], vertices[7]), + (vertices[2], vertices[7], vertices[6]), + (vertices[3], vertices[0], vertices[4]), + (vertices[3], vertices[4], vertices[7]), + (vertices[4], vertices[5], vertices[6]), + (vertices[4], vertices[6], vertices[7])] + +write_stl("cube.stl") From 3e772c52ea7e7e1c118b45a562121747e763c772 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 5 Jul 2023 14:48:10 +0330 Subject: [PATCH 533/775] Auto format doc --- files/generate_cube.py | 41 ++++++++++++++++++++++++-------------- files/generate_cylinder.py | 5 +++-- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/files/generate_cube.py b/files/generate_cube.py index a7dd62163..39fc8e954 100644 --- a/files/generate_cube.py +++ b/files/generate_cube.py @@ -1,5 +1,5 @@ def write_stl(filename): - with open(filename, 'w') as f: + with open(filename, "w") as f: f.write("solid cube\n") for face in faces: f.write(" facet normal 0 0 0\n") @@ -10,26 +10,37 @@ def write_stl(filename): f.write(" endfacet\n") f.write("endsolid cube") + width = 12 height = 22 length = 100 # Define the 8 vertices of the cube -vertices = [(0, 0, 0), (length, 0, 0), (length, width, 0), (0, width, 0), - (0, 0, height), (length, 0, height), (length, width, height), (0, width, height)] +vertices = [ + (0, 0, 0), + (length, 0, 0), + (length, width, 0), + (0, width, 0), + (0, 0, height), + (length, 0, height), + (length, width, height), + (0, width, height), +] # Define the 12 triangles composing the cube -faces = [(vertices[0], vertices[1], vertices[2]), - (vertices[0], vertices[2], vertices[3]), - (vertices[0], vertices[1], vertices[5]), - (vertices[0], vertices[5], vertices[4]), - (vertices[1], vertices[2], vertices[6]), - (vertices[1], vertices[6], vertices[5]), - (vertices[2], vertices[3], vertices[7]), - (vertices[2], vertices[7], vertices[6]), - (vertices[3], vertices[0], vertices[4]), - (vertices[3], vertices[4], vertices[7]), - (vertices[4], vertices[5], vertices[6]), - (vertices[4], vertices[6], vertices[7])] +faces = [ + (vertices[0], vertices[1], vertices[2]), + (vertices[0], vertices[2], vertices[3]), + (vertices[0], vertices[1], vertices[5]), + (vertices[0], vertices[5], vertices[4]), + (vertices[1], vertices[2], vertices[6]), + (vertices[1], vertices[6], vertices[5]), + (vertices[2], vertices[3], vertices[7]), + (vertices[2], vertices[7], vertices[6]), + (vertices[3], vertices[0], vertices[4]), + (vertices[3], vertices[4], vertices[7]), + (vertices[4], vertices[5], vertices[6]), + (vertices[4], vertices[6], vertices[7]), +] write_stl("cube.stl") diff --git a/files/generate_cylinder.py b/files/generate_cylinder.py index 28abe72ee..c7d4696e6 100644 --- a/files/generate_cylinder.py +++ b/files/generate_cylinder.py @@ -1,8 +1,9 @@ import math + # Cylinder is shifted by {+radius} along the Z axis to be above the XY plane. def generate_cylinder_stl(radius, length, num_triangles, output_file): - with open(output_file, 'w') as stl_file: + with open(output_file, "w") as stl_file: stl_file.write("solid cylinder\n") angle_step = 2 * math.pi / num_triangles @@ -58,4 +59,4 @@ def generate_cylinder_stl(radius, length, num_triangles, output_file): radius = 12 length = 100 num_triangles = 36 -generate_cylinder_stl(radius, length, num_triangles,output_filename) +generate_cylinder_stl(radius, length, num_triangles, output_filename) From 113cfa63781b78790eb27f38c9290cb57fd2fecb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 5 Jul 2023 15:25:50 +0330 Subject: [PATCH 534/775] Generic names --- examples/finite_elements/main.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index c9e14a91c..dc62c0813 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -77,79 +77,79 @@ func main() { } // create the SDF from the STL mesh - hingeSdf, err := obj.ImportSTL(file, 20, 3, 5) + inSdf, err := obj.ImportSTL(file, 20, 3, 5) if err != nil { log.Fatalf("error: %s", err) } // tet4 i.e. 4-node tetrahedron - err = fe(hingeSdf, 50, render.Linear, render.Tetrahedral, "hinge-tet4.inp") + err = fe(inSdf, 50, render.Linear, render.Tetrahedral, "tet4.inp") if err != nil { log.Fatalf("error: %s", err) } // tet4 i.e. 4-node tetrahedron - err = fePartial(hingeSdf, 50, render.Linear, render.Tetrahedral, "hinge-partial-tet4.inp", 0, 5) + err = fePartial(inSdf, 50, render.Linear, render.Tetrahedral, "partial-tet4.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fe(hingeSdf, 50, render.Quadratic, render.Tetrahedral, "hinge-tet10.inp") + err = fe(inSdf, 50, render.Quadratic, render.Tetrahedral, "tet10.inp") if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fePartial(hingeSdf, 50, render.Quadratic, render.Tetrahedral, "hinge-partial-tet10.inp", 0, 5) + err = fePartial(inSdf, 50, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fe(hingeSdf, 50, render.Linear, render.Hexahedral, "hinge-hex8.inp") + err = fe(inSdf, 50, render.Linear, render.Hexahedral, "hex8.inp") if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fePartial(hingeSdf, 50, render.Linear, render.Hexahedral, "hinge-partial-hex8.inp", 0, 5) + err = fePartial(inSdf, 50, render.Linear, render.Hexahedral, "partial-hex8.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fe(hingeSdf, 50, render.Quadratic, render.Hexahedral, "hinge-hex20.inp") + err = fe(inSdf, 50, render.Quadratic, render.Hexahedral, "hex20.inp") if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fePartial(hingeSdf, 50, render.Quadratic, render.Hexahedral, "hinge-partial-hex20.inp", 0, 5) + err = fePartial(inSdf, 50, render.Quadratic, render.Hexahedral, "partial-hex20.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fe(hingeSdf, 50, render.Linear, render.Both, "hinge-hex8tet4.inp") + err = fe(inSdf, 50, render.Linear, render.Both, "hex8tet4.inp") if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fePartial(hingeSdf, 50, render.Linear, render.Both, "hinge-partial-hex8tet4.inp", 0, 5) + err = fePartial(inSdf, 50, render.Linear, render.Both, "partial-hex8tet4.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fe(hingeSdf, 50, render.Quadratic, render.Both, "hinge-hex20tet10.inp") + err = fe(inSdf, 50, render.Quadratic, render.Both, "hex20tet10.inp") if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fePartial(hingeSdf, 50, render.Quadratic, render.Both, "hinge-partial-hex20tet10.inp", 0, 5) + err = fePartial(inSdf, 50, render.Quadratic, render.Both, "partial-hex20tet10.inp", 0, 5) if err != nil { log.Fatalf("error: %s", err) } From 580fec87248a6183830de97d760089d4312c0ce4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 6 Jul 2023 09:48:17 +0330 Subject: [PATCH 535/775] Remove other STLs, keep teapot --- examples/finite_elements/main.go | 14 +- files/cube.stl | 86 - files/generate_cube.py | 46 - files/generate_cylinder.py | 62 - files/hinge.stl | 8486 ------------------------------ 5 files changed, 7 insertions(+), 8687 deletions(-) delete mode 100644 files/cube.stl delete mode 100644 files/generate_cube.py delete mode 100644 files/generate_cylinder.py delete mode 100644 files/hinge.stl diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index dc62c0813..22380a7ff 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -68,7 +68,7 @@ func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shap // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - stl := "../../files/hinge.stl" + stl := "../../files/teapot.stl" // read the stl file. file, err := os.OpenFile(stl, os.O_RDONLY, 0400) @@ -89,7 +89,7 @@ func main() { } // tet4 i.e. 4-node tetrahedron - err = fePartial(inSdf, 50, render.Linear, render.Tetrahedral, "partial-tet4.inp", 0, 5) + err = fePartial(inSdf, 50, render.Linear, render.Tetrahedral, "partial-tet4.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -101,7 +101,7 @@ func main() { } // tet10 i.e. 10-node tetrahedron - err = fePartial(inSdf, 50, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", 0, 5) + err = fePartial(inSdf, 50, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -113,7 +113,7 @@ func main() { } // hex8 i.e. 8-node hexahedron - err = fePartial(inSdf, 50, render.Linear, render.Hexahedral, "partial-hex8.inp", 0, 5) + err = fePartial(inSdf, 50, render.Linear, render.Hexahedral, "partial-hex8.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -125,7 +125,7 @@ func main() { } // hex20 i.e. 20-node hexahedron - err = fePartial(inSdf, 50, render.Quadratic, render.Hexahedral, "partial-hex20.inp", 0, 5) + err = fePartial(inSdf, 50, render.Quadratic, render.Hexahedral, "partial-hex20.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -137,7 +137,7 @@ func main() { } // hex8 and tet4 - err = fePartial(inSdf, 50, render.Linear, render.Both, "partial-hex8tet4.inp", 0, 5) + err = fePartial(inSdf, 50, render.Linear, render.Both, "partial-hex8tet4.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } @@ -149,7 +149,7 @@ func main() { } // hex20 and tet10 - err = fePartial(inSdf, 50, render.Quadratic, render.Both, "partial-hex20tet10.inp", 0, 5) + err = fePartial(inSdf, 50, render.Quadratic, render.Both, "partial-hex20tet10.inp", 0, 15) if err != nil { log.Fatalf("error: %s", err) } diff --git a/files/cube.stl b/files/cube.stl deleted file mode 100644 index eabbe9e26..000000000 --- a/files/cube.stl +++ /dev/null @@ -1,86 +0,0 @@ -solid mesh -facet normal -1.0 0.0 0.0 - outer loop - vertex -10.0 -1.0 -1.0 - vertex -10.0 -1.0 1.0 - vertex -10.0 1.0 1.0 - endloop -endfacet -facet normal -1.0 0.0 -0.0 - outer loop - vertex -10.0 1.0 1.0 - vertex -10.0 1.0 -1.0 - vertex -10.0 -1.0 -1.0 - endloop -endfacet -facet normal 0.0 1.0 0.0 - outer loop - vertex -10.0 1.0 -1.0 - vertex -10.0 1.0 1.0 - vertex 10.0 1.0 1.0 - endloop -endfacet -facet normal 0.0 1.0 0.0 - outer loop - vertex 10.0 1.0 1.0 - vertex 10.0 1.0 -1.0 - vertex -10.0 1.0 -1.0 - endloop -endfacet -facet normal 1.0 0.0 -0.0 - outer loop - vertex 10.0 1.0 -1.0 - vertex 10.0 1.0 1.0 - vertex 10.0 -1.0 1.0 - endloop -endfacet -facet normal 1.0 0.0 0.0 - outer loop - vertex 10.0 -1.0 1.0 - vertex 10.0 -1.0 -1.0 - vertex 10.0 1.0 -1.0 - endloop -endfacet -facet normal 0.0 -1.0 0.0 - outer loop - vertex -10.0 -1.0 1.0 - vertex -10.0 -1.0 -1.0 - vertex 10.0 -1.0 -1.0 - endloop -endfacet -facet normal 0.0 -1.0 0.0 - outer loop - vertex 10.0 -1.0 -1.0 - vertex 10.0 -1.0 1.0 - vertex -10.0 -1.0 1.0 - endloop -endfacet -facet normal 0.0 0.0 1.0 - outer loop - vertex -10.0 -1.0 1.0 - vertex 10.0 -1.0 1.0 - vertex 10.0 1.0 1.0 - endloop -endfacet -facet normal 0.0 0.0 1.0 - outer loop - vertex 10.0 1.0 1.0 - vertex -10.0 1.0 1.0 - vertex -10.0 -1.0 1.0 - endloop -endfacet -facet normal 0.0 0.0 -1.0 - outer loop - vertex -10.0 -1.0 -1.0 - vertex -10.0 1.0 -1.0 - vertex 10.0 1.0 -1.0 - endloop -endfacet -facet normal 0.0 -0.0 -1.0 - outer loop - vertex 10.0 1.0 -1.0 - vertex 10.0 -1.0 -1.0 - vertex -10.0 -1.0 -1.0 - endloop -endfacet -endsolid mesh diff --git a/files/generate_cube.py b/files/generate_cube.py deleted file mode 100644 index 39fc8e954..000000000 --- a/files/generate_cube.py +++ /dev/null @@ -1,46 +0,0 @@ -def write_stl(filename): - with open(filename, "w") as f: - f.write("solid cube\n") - for face in faces: - f.write(" facet normal 0 0 0\n") - f.write(" outer loop\n") - for vertex in face: - f.write(" vertex {} {} {}\n".format(*vertex)) - f.write(" endloop\n") - f.write(" endfacet\n") - f.write("endsolid cube") - - -width = 12 -height = 22 -length = 100 - -# Define the 8 vertices of the cube -vertices = [ - (0, 0, 0), - (length, 0, 0), - (length, width, 0), - (0, width, 0), - (0, 0, height), - (length, 0, height), - (length, width, height), - (0, width, height), -] - -# Define the 12 triangles composing the cube -faces = [ - (vertices[0], vertices[1], vertices[2]), - (vertices[0], vertices[2], vertices[3]), - (vertices[0], vertices[1], vertices[5]), - (vertices[0], vertices[5], vertices[4]), - (vertices[1], vertices[2], vertices[6]), - (vertices[1], vertices[6], vertices[5]), - (vertices[2], vertices[3], vertices[7]), - (vertices[2], vertices[7], vertices[6]), - (vertices[3], vertices[0], vertices[4]), - (vertices[3], vertices[4], vertices[7]), - (vertices[4], vertices[5], vertices[6]), - (vertices[4], vertices[6], vertices[7]), -] - -write_stl("cube.stl") diff --git a/files/generate_cylinder.py b/files/generate_cylinder.py deleted file mode 100644 index c7d4696e6..000000000 --- a/files/generate_cylinder.py +++ /dev/null @@ -1,62 +0,0 @@ -import math - - -# Cylinder is shifted by {+radius} along the Z axis to be above the XY plane. -def generate_cylinder_stl(radius, length, num_triangles, output_file): - with open(output_file, "w") as stl_file: - stl_file.write("solid cylinder\n") - - angle_step = 2 * math.pi / num_triangles - - for i in range(num_triangles): - angle1 = i * angle_step - angle2 = (i + 1) * angle_step - - y1, z1 = radius * math.cos(angle1), radius * math.sin(angle1) - y2, z2 = radius * math.cos(angle2), radius * math.sin(angle2) - - # Base triangle - stl_file.write("facet normal -1.0 0.0 0.0\n") - stl_file.write("outer loop\n") - stl_file.write(f"vertex 0.0 0.0 {0.0+radius}\n") - stl_file.write(f"vertex 0.0 {y2} {z2+radius}\n") - stl_file.write(f"vertex 0.0 {y1} {z1+radius}\n") - stl_file.write("endloop\n") - stl_file.write("endfacet\n") - - # Top triangle - stl_file.write("facet normal 1.0 0.0 0.0\n") - stl_file.write("outer loop\n") - stl_file.write(f"vertex {length} 0.0 {0.0+radius}\n") - stl_file.write(f"vertex {length} {y1} {z1+radius}\n") - stl_file.write(f"vertex {length} {y2} {z2+radius}\n") - stl_file.write("endloop\n") - stl_file.write("endfacet\n") - - # Side triangles - normal = f"0.0 {math.cos(angle1)} {math.sin(angle1)}" - stl_file.write(f"facet normal {normal}\n") - stl_file.write("outer loop\n") - stl_file.write(f"vertex 0.0 {y1} {z1+radius}\n") - stl_file.write(f"vertex 0.0 {y2} {z2+radius}\n") - stl_file.write(f"vertex {length} {y1} {z1+radius}\n") - stl_file.write("endloop\n") - stl_file.write("endfacet\n") - - normal = f"0.0 {math.cos(angle2)} {math.sin(angle2)}" - stl_file.write(f"facet normal {normal}\n") - stl_file.write("outer loop\n") - stl_file.write(f"vertex 0.0 {y2} {z2+radius}\n") - stl_file.write(f"vertex {length} {y2} {z2+radius}\n") - stl_file.write(f"vertex {length} {y1} {z1+radius}\n") - stl_file.write("endloop\n") - stl_file.write("endfacet\n") - - stl_file.write("endsolid cylinder\n") - - -output_filename = "cylinder.stl" -radius = 12 -length = 100 -num_triangles = 36 -generate_cylinder_stl(radius, length, num_triangles, output_filename) diff --git a/files/hinge.stl b/files/hinge.stl deleted file mode 100644 index acb421d45..000000000 --- a/files/hinge.stl +++ /dev/null @@ -1,8486 +0,0 @@ -solid - facet normal 5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 3.832020e+001 1.706140e+001 5.000000e+000 - vertex 3.837337e+001 1.645363e+001 5.000000e+000 - vertex 3.932020e+001 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 3.935818e+001 1.749552e+001 4.399139e+000 - vertex 3.832020e+001 1.706140e+001 5.000000e+000 - vertex 3.932020e+001 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 3.935818e+001 1.749552e+001 4.399139e+000 - vertex 3.837337e+001 1.766917e+001 5.000000e+000 - vertex 3.832020e+001 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 3.935818e+001 1.749552e+001 4.399139e+000 - vertex 3.853128e+001 1.825847e+001 5.000000e+000 - vertex 3.837337e+001 1.766917e+001 5.000000e+000 - endloop - endfacet - facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 3.935818e+001 1.749552e+001 4.399139e+000 - vertex 3.947097e+001 1.791645e+001 4.399139e+000 - vertex 3.853128e+001 1.825847e+001 5.000000e+000 - endloop - endfacet - facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 3.853128e+001 1.825847e+001 5.000000e+000 - vertex 3.947097e+001 1.791645e+001 4.399139e+000 - vertex 3.878911e+001 1.881140e+001 5.000000e+000 - endloop - endfacet - facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 3.878911e+001 1.881140e+001 5.000000e+000 - vertex 3.947097e+001 1.791645e+001 4.399139e+000 - vertex 3.965514e+001 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 3.913904e+001 1.931116e+001 5.000000e+000 - vertex 3.965514e+001 1.831140e+001 4.399139e+000 - vertex 3.990509e+001 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 4.021323e+001 1.897651e+001 4.399139e+000 - vertex 3.913904e+001 1.931116e+001 5.000000e+000 - vertex 3.990509e+001 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 4.021323e+001 1.897651e+001 4.399139e+000 - vertex 3.957044e+001 1.974256e+001 5.000000e+000 - vertex 3.913904e+001 1.931116e+001 5.000000e+000 - endloop - endfacet - facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 4.021323e+001 1.897651e+001 4.399139e+000 - vertex 4.057020e+001 1.922646e+001 4.399139e+000 - vertex 3.957044e+001 1.974256e+001 5.000000e+000 - endloop - endfacet - facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 3.957044e+001 1.974256e+001 5.000000e+000 - vertex 4.057020e+001 1.922646e+001 4.399139e+000 - vertex 4.007020e+001 2.009249e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 4.007020e+001 2.009249e+001 5.000000e+000 - vertex 4.057020e+001 1.922646e+001 4.399139e+000 - vertex 4.062313e+001 2.035032e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 4.062313e+001 2.035032e+001 5.000000e+000 - vertex 4.057020e+001 1.922646e+001 4.399139e+000 - vertex 4.096515e+001 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 4.121243e+001 2.050823e+001 5.000000e+000 - vertex 4.096515e+001 1.941063e+001 4.399139e+000 - vertex 4.138608e+001 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 4.182020e+001 1.956140e+001 4.399139e+000 - vertex 4.121243e+001 2.050823e+001 5.000000e+000 - vertex 4.138608e+001 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 4.182020e+001 1.956140e+001 4.399139e+000 - vertex 4.182020e+001 2.056140e+001 5.000000e+000 - vertex 4.121243e+001 2.050823e+001 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 4.182020e+001 1.956140e+001 4.399139e+000 - vertex 4.225432e+001 1.952342e+001 4.399139e+000 - vertex 4.182020e+001 2.056140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 4.182020e+001 2.056140e+001 5.000000e+000 - vertex 4.225432e+001 1.952342e+001 4.399139e+000 - vertex 4.242797e+001 2.050823e+001 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 4.242797e+001 2.050823e+001 5.000000e+000 - vertex 4.225432e+001 1.952342e+001 4.399139e+000 - vertex 4.267525e+001 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 4.301727e+001 2.035032e+001 5.000000e+000 - vertex 4.267525e+001 1.941063e+001 4.399139e+000 - vertex 4.307020e+001 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 4.357020e+001 2.009249e+001 5.000000e+000 - vertex 4.307020e+001 1.922646e+001 4.399139e+000 - vertex 4.342717e+001 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 4.406996e+001 1.974256e+001 5.000000e+000 - vertex 4.342717e+001 1.897651e+001 4.399139e+000 - vertex 4.373531e+001 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 4.450136e+001 1.931116e+001 5.000000e+000 - vertex 4.373531e+001 1.866837e+001 4.399139e+000 - vertex 4.398526e+001 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 4.485129e+001 1.881140e+001 5.000000e+000 - vertex 4.398526e+001 1.831140e+001 4.399139e+000 - vertex 4.510912e+001 1.825847e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 4.485129e+001 1.881140e+001 5.000000e+000 - vertex 4.450136e+001 1.931116e+001 5.000000e+000 - vertex 4.398526e+001 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 3.837337e+001 1.645363e+001 5.000000e+000 - vertex 3.853128e+001 1.586433e+001 5.000000e+000 - vertex 3.947097e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal 4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 3.935818e+001 1.662728e+001 4.399139e+000 - vertex 3.837337e+001 1.645363e+001 5.000000e+000 - vertex 3.947097e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal 5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 3.935818e+001 1.662728e+001 4.399139e+000 - vertex 3.932020e+001 1.706140e+001 4.399139e+000 - vertex 3.837337e+001 1.645363e+001 5.000000e+000 - endloop - endfacet - facet normal 4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 3.853128e+001 1.586433e+001 5.000000e+000 - vertex 3.878911e+001 1.531140e+001 5.000000e+000 - vertex 3.965514e+001 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 3.947097e+001 1.620635e+001 4.399139e+000 - vertex 3.853128e+001 1.586433e+001 5.000000e+000 - vertex 3.965514e+001 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 3.878911e+001 1.531140e+001 5.000000e+000 - vertex 3.913904e+001 1.481164e+001 5.000000e+000 - vertex 3.990509e+001 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 3.965514e+001 1.581140e+001 4.399139e+000 - vertex 3.878911e+001 1.531140e+001 5.000000e+000 - vertex 3.990509e+001 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal 3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 3.913904e+001 1.481164e+001 5.000000e+000 - vertex 3.957044e+001 1.438024e+001 5.000000e+000 - vertex 3.990509e+001 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal 3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 3.990509e+001 1.545443e+001 4.399139e+000 - vertex 3.957044e+001 1.438024e+001 5.000000e+000 - vertex 4.021323e+001 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal 2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 4.021323e+001 1.514629e+001 4.399139e+000 - vertex 3.957044e+001 1.438024e+001 5.000000e+000 - vertex 4.057020e+001 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal 2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 4.057020e+001 1.489634e+001 4.399139e+000 - vertex 3.957044e+001 1.438024e+001 5.000000e+000 - vertex 4.007020e+001 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 4.062313e+001 1.377248e+001 5.000000e+000 - vertex 4.057020e+001 1.489634e+001 4.399139e+000 - vertex 4.007020e+001 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 4.062313e+001 1.377248e+001 5.000000e+000 - vertex 4.096515e+001 1.471217e+001 4.399139e+000 - vertex 4.057020e+001 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal 1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 4.062313e+001 1.377248e+001 5.000000e+000 - vertex 4.121243e+001 1.361457e+001 5.000000e+000 - vertex 4.096515e+001 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal 1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 4.096515e+001 1.471217e+001 4.399139e+000 - vertex 4.121243e+001 1.361457e+001 5.000000e+000 - vertex 4.138608e+001 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 4.138608e+001 1.459938e+001 4.399139e+000 - vertex 4.121243e+001 1.361457e+001 5.000000e+000 - vertex 4.182020e+001 1.456140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 4.182020e+001 1.456140e+001 4.399139e+000 - vertex 4.121243e+001 1.361457e+001 5.000000e+000 - vertex 4.182020e+001 1.356140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 4.225432e+001 1.459938e+001 4.399139e+000 - vertex 4.182020e+001 1.356140e+001 5.000000e+000 - vertex 4.242797e+001 1.361457e+001 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 4.267525e+001 1.471217e+001 4.399139e+000 - vertex 4.242797e+001 1.361457e+001 5.000000e+000 - vertex 4.301727e+001 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal -2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 4.357020e+001 1.403031e+001 5.000000e+000 - vertex 4.267525e+001 1.471217e+001 4.399139e+000 - vertex 4.301727e+001 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal -2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 4.357020e+001 1.403031e+001 5.000000e+000 - vertex 4.307020e+001 1.489634e+001 4.399139e+000 - vertex 4.267525e+001 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 4.357020e+001 1.403031e+001 5.000000e+000 - vertex 4.406996e+001 1.438024e+001 5.000000e+000 - vertex 4.307020e+001 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 4.307020e+001 1.489634e+001 4.399139e+000 - vertex 4.406996e+001 1.438024e+001 5.000000e+000 - vertex 4.342717e+001 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal -3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 4.342717e+001 1.514629e+001 4.399139e+000 - vertex 4.406996e+001 1.438024e+001 5.000000e+000 - vertex 4.450136e+001 1.481164e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 4.373531e+001 1.545443e+001 4.399139e+000 - vertex 4.450136e+001 1.481164e+001 5.000000e+000 - vertex 4.485129e+001 1.531140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 4.398526e+001 1.581140e+001 4.399139e+000 - vertex 4.485129e+001 1.531140e+001 5.000000e+000 - vertex 4.510912e+001 1.586433e+001 5.000000e+000 - endloop - endfacet - facet normal -4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 4.416943e+001 1.620635e+001 4.399139e+000 - vertex 4.510912e+001 1.586433e+001 5.000000e+000 - vertex 4.428222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 4.416943e+001 1.620635e+001 4.399139e+000 - vertex 4.398526e+001 1.581140e+001 4.399139e+000 - vertex 4.510912e+001 1.586433e+001 5.000000e+000 - endloop - endfacet - facet normal -4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 4.510912e+001 1.586433e+001 5.000000e+000 - vertex 4.526703e+001 1.645363e+001 5.000000e+000 - vertex 4.428222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 4.428222e+001 1.662728e+001 4.399139e+000 - vertex 4.526703e+001 1.645363e+001 5.000000e+000 - vertex 4.432020e+001 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal -5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 4.432020e+001 1.706140e+001 4.399139e+000 - vertex 4.526703e+001 1.645363e+001 5.000000e+000 - vertex 4.532020e+001 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 4.428222e+001 1.749552e+001 4.399139e+000 - vertex 4.532020e+001 1.706140e+001 5.000000e+000 - vertex 4.526703e+001 1.766917e+001 5.000000e+000 - endloop - endfacet - facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 4.416943e+001 1.791645e+001 4.399139e+000 - vertex 4.526703e+001 1.766917e+001 5.000000e+000 - vertex 4.510912e+001 1.825847e+001 5.000000e+000 - endloop - endfacet - facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 4.398526e+001 1.831140e+001 4.399139e+000 - vertex 4.416943e+001 1.791645e+001 4.399139e+000 - vertex 4.510912e+001 1.825847e+001 5.000000e+000 - endloop - endfacet - facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 4.450136e+001 1.931116e+001 5.000000e+000 - vertex 4.406996e+001 1.974256e+001 5.000000e+000 - vertex 4.373531e+001 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 4.406996e+001 1.974256e+001 5.000000e+000 - vertex 4.357020e+001 2.009249e+001 5.000000e+000 - vertex 4.342717e+001 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 4.357020e+001 2.009249e+001 5.000000e+000 - vertex 4.301727e+001 2.035032e+001 5.000000e+000 - vertex 4.307020e+001 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 4.301727e+001 2.035032e+001 5.000000e+000 - vertex 4.242797e+001 2.050823e+001 5.000000e+000 - vertex 4.267525e+001 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 4.121243e+001 2.050823e+001 5.000000e+000 - vertex 4.062313e+001 2.035032e+001 5.000000e+000 - vertex 4.096515e+001 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 3.913904e+001 1.931116e+001 5.000000e+000 - vertex 3.878911e+001 1.881140e+001 5.000000e+000 - vertex 3.965514e+001 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 4.416943e+001 1.791645e+001 4.399139e+000 - vertex 4.428222e+001 1.749552e+001 4.399139e+000 - vertex 4.526703e+001 1.766917e+001 5.000000e+000 - endloop - endfacet - facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 4.428222e+001 1.749552e+001 4.399139e+000 - vertex 4.432020e+001 1.706140e+001 4.399139e+000 - vertex 4.532020e+001 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 4.398526e+001 1.581140e+001 4.399139e+000 - vertex 4.373531e+001 1.545443e+001 4.399139e+000 - vertex 4.485129e+001 1.531140e+001 5.000000e+000 - endloop - endfacet - facet normal -3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 4.342717e+001 1.514629e+001 4.399139e+000 - vertex 4.450136e+001 1.481164e+001 5.000000e+000 - vertex 4.373531e+001 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal -1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 4.267525e+001 1.471217e+001 4.399139e+000 - vertex 4.225432e+001 1.459938e+001 4.399139e+000 - vertex 4.242797e+001 1.361457e+001 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 4.225432e+001 1.459938e+001 4.399139e+000 - vertex 4.182020e+001 1.456140e+001 4.399139e+000 - vertex 4.182020e+001 1.356140e+001 5.000000e+000 - endloop - endfacet - facet normal -9.961947e-001 8.715574e-002 0.000000e+000 - outer loop - vertex 4.432020e+001 1.706140e+001 -8.881784e-016 - vertex 4.428222e+001 1.662728e+001 -8.881784e-016 - vertex 4.428222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.961947e-001 8.715574e-002 0.000000e+000 - outer loop - vertex 4.432020e+001 1.706140e+001 4.399139e+000 - vertex 4.432020e+001 1.706140e+001 -8.881784e-016 - vertex 4.428222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 - outer loop - vertex 4.432020e+001 1.706140e+001 4.399139e+000 - vertex 4.428222e+001 1.749552e+001 -8.881784e-016 - vertex 4.432020e+001 1.706140e+001 -8.881784e-016 - endloop - endfacet - facet normal -9.961947e-001 -8.715574e-002 -9.048915e-016 - outer loop - vertex 4.432020e+001 1.706140e+001 4.399139e+000 - vertex 4.428222e+001 1.749552e+001 4.399139e+000 - vertex 4.428222e+001 1.749552e+001 -8.881784e-016 - endloop - endfacet - facet normal -9.659258e-001 -2.588190e-001 5.300545e-016 - outer loop - vertex 4.428222e+001 1.749552e+001 -8.881784e-016 - vertex 4.428222e+001 1.749552e+001 4.399139e+000 - vertex 4.416943e+001 1.791645e+001 -8.881784e-016 - endloop - endfacet - facet normal -9.659258e-001 -2.588190e-001 -1.030095e-015 - outer loop - vertex 4.416943e+001 1.791645e+001 -8.881784e-016 - vertex 4.428222e+001 1.749552e+001 4.399139e+000 - vertex 4.416943e+001 1.791645e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 -4.226183e-001 1.440206e-016 - outer loop - vertex 4.398526e+001 1.831140e+001 -8.881784e-016 - vertex 4.416943e+001 1.791645e+001 4.399139e+000 - vertex 4.398526e+001 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 -5.735764e-001 -1.586601e-015 - outer loop - vertex 4.373531e+001 1.866837e+001 -8.881784e-016 - vertex 4.398526e+001 1.831140e+001 4.399139e+000 - vertex 4.373531e+001 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015 - outer loop - vertex 4.342717e+001 1.897651e+001 -8.881784e-016 - vertex 4.373531e+001 1.866837e+001 4.399139e+000 - vertex 4.342717e+001 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 -8.191520e-001 -1.324456e-015 - outer loop - vertex 4.307020e+001 1.922646e+001 -8.881784e-016 - vertex 4.342717e+001 1.897651e+001 4.399139e+000 - vertex 4.307020e+001 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 -9.063078e-001 -1.217252e-015 - outer loop - vertex 4.267525e+001 1.941063e+001 -8.881784e-016 - vertex 4.307020e+001 1.922646e+001 4.399139e+000 - vertex 4.267525e+001 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015 - outer loop - vertex 4.225432e+001 1.952342e+001 -8.881784e-016 - vertex 4.267525e+001 1.941063e+001 4.399139e+000 - vertex 4.225432e+001 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 - outer loop - vertex 4.182020e+001 1.956140e+001 -8.881784e-016 - vertex 4.225432e+001 1.952342e+001 4.399139e+000 - vertex 4.182020e+001 1.956140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016 - outer loop - vertex 4.138608e+001 1.952342e+001 -8.881784e-016 - vertex 4.182020e+001 1.956140e+001 4.399139e+000 - vertex 4.138608e+001 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 -9.659258e-001 -2.500203e-016 - outer loop - vertex 4.096515e+001 1.941063e+001 -8.881784e-016 - vertex 4.138608e+001 1.952342e+001 4.399139e+000 - vertex 4.096515e+001 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 -9.063078e-001 -9.292106e-016 - outer loop - vertex 4.057020e+001 1.922646e+001 -8.881784e-016 - vertex 4.096515e+001 1.941063e+001 4.399139e+000 - vertex 4.057020e+001 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 -8.191520e-001 -9.250596e-016 - outer loop - vertex 4.021323e+001 1.897651e+001 -8.881784e-016 - vertex 4.057020e+001 1.922646e+001 4.399139e+000 - vertex 4.021323e+001 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 -7.071068e-001 -1.142109e-015 - outer loop - vertex 3.990509e+001 1.866837e+001 -8.881784e-016 - vertex 4.021323e+001 1.897651e+001 4.399139e+000 - vertex 3.990509e+001 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 -5.735764e-001 -1.059565e-015 - outer loop - vertex 3.965514e+001 1.831140e+001 -8.881784e-016 - vertex 3.990509e+001 1.866837e+001 4.399139e+000 - vertex 3.965514e+001 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 -4.226183e-001 -4.853241e-016 - outer loop - vertex 3.947097e+001 1.791645e+001 -8.881784e-016 - vertex 3.965514e+001 1.831140e+001 4.399139e+000 - vertex 3.947097e+001 1.791645e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016 - outer loop - vertex 3.935818e+001 1.749552e+001 -8.881784e-016 - vertex 3.947097e+001 1.791645e+001 4.399139e+000 - vertex 3.935818e+001 1.749552e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 - outer loop - vertex 3.932020e+001 1.706140e+001 -8.881784e-016 - vertex 3.935818e+001 1.749552e+001 4.399139e+000 - vertex 3.932020e+001 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 8.715574e-002 7.038636e-017 - outer loop - vertex 3.935818e+001 1.662728e+001 -8.881784e-016 - vertex 3.932020e+001 1.706140e+001 4.399139e+000 - vertex 3.935818e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 2.588190e-001 0.000000e+000 - outer loop - vertex 3.947097e+001 1.620635e+001 -8.881784e-016 - vertex 3.935818e+001 1.662728e+001 4.399139e+000 - vertex 3.947097e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 4.226183e-001 0.000000e+000 - outer loop - vertex 3.965514e+001 1.581140e+001 -8.881784e-016 - vertex 3.947097e+001 1.620635e+001 4.399139e+000 - vertex 3.965514e+001 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 5.735764e-001 2.316081e-016 - outer loop - vertex 3.990509e+001 1.545443e+001 -8.881784e-016 - vertex 3.965514e+001 1.581140e+001 4.399139e+000 - vertex 3.990509e+001 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 7.071068e-001 2.855272e-016 - outer loop - vertex 4.021323e+001 1.514629e+001 -8.881784e-016 - vertex 3.990509e+001 1.545443e+001 4.399139e+000 - vertex 4.021323e+001 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 8.191520e-001 3.307707e-016 - outer loop - vertex 4.057020e+001 1.489634e+001 -8.881784e-016 - vertex 4.021323e+001 1.514629e+001 4.399139e+000 - vertex 4.057020e+001 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 9.063078e-001 -6.826070e-016 - outer loop - vertex 4.096515e+001 1.471217e+001 -8.881784e-016 - vertex 4.057020e+001 1.489634e+001 4.399139e+000 - vertex 4.096515e+001 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 9.659258e-001 -4.180408e-016 - outer loop - vertex 4.138608e+001 1.459938e+001 -8.881784e-016 - vertex 4.096515e+001 1.471217e+001 4.399139e+000 - vertex 4.138608e+001 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 9.961947e-001 0.000000e+000 - outer loop - vertex 4.182020e+001 1.456140e+001 -8.881784e-016 - vertex 4.138608e+001 1.459938e+001 4.399139e+000 - vertex 4.182020e+001 1.456140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 9.961947e-001 0.000000e+000 - outer loop - vertex 4.225432e+001 1.459938e+001 -8.881784e-016 - vertex 4.182020e+001 1.456140e+001 4.399139e+000 - vertex 4.225432e+001 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 9.659258e-001 2.800343e-017 - outer loop - vertex 4.267525e+001 1.471217e+001 -8.881784e-016 - vertex 4.225432e+001 1.459938e+001 4.399139e+000 - vertex 4.267525e+001 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 9.063078e-001 -3.659639e-016 - outer loop - vertex 4.307020e+001 1.489634e+001 -8.881784e-016 - vertex 4.267525e+001 1.471217e+001 4.399139e+000 - vertex 4.307020e+001 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 8.191520e-001 5.956618e-016 - outer loop - vertex 4.342717e+001 1.514629e+001 -8.881784e-016 - vertex 4.307020e+001 1.489634e+001 4.399139e+000 - vertex 4.342717e+001 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 7.071068e-001 0.000000e+000 - outer loop - vertex 4.373531e+001 1.545443e+001 -8.881784e-016 - vertex 4.342717e+001 1.514629e+001 4.399139e+000 - vertex 4.373531e+001 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 5.735764e-001 0.000000e+000 - outer loop - vertex 4.398526e+001 1.581140e+001 -8.881784e-016 - vertex 4.373531e+001 1.545443e+001 4.399139e+000 - vertex 4.398526e+001 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 4.226183e-001 0.000000e+000 - outer loop - vertex 4.416943e+001 1.620635e+001 -8.881784e-016 - vertex 4.398526e+001 1.581140e+001 4.399139e+000 - vertex 4.416943e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal -9.659258e-001 2.588190e-001 0.000000e+000 - outer loop - vertex 4.428222e+001 1.662728e+001 -8.881784e-016 - vertex 4.416943e+001 1.620635e+001 4.399139e+000 - vertex 4.428222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.659258e-001 2.588190e-001 0.000000e+000 - outer loop - vertex 4.428222e+001 1.662728e+001 -8.881784e-016 - vertex 4.416943e+001 1.620635e+001 -8.881784e-016 - vertex 4.416943e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 4.226183e-001 0.000000e+000 - outer loop - vertex 4.416943e+001 1.620635e+001 -8.881784e-016 - vertex 4.398526e+001 1.581140e+001 -8.881784e-016 - vertex 4.398526e+001 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 5.735764e-001 0.000000e+000 - outer loop - vertex 4.398526e+001 1.581140e+001 -8.881784e-016 - vertex 4.373531e+001 1.545443e+001 -8.881784e-016 - vertex 4.373531e+001 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 7.071068e-001 8.614567e-016 - outer loop - vertex 4.373531e+001 1.545443e+001 -8.881784e-016 - vertex 4.342717e+001 1.514629e+001 -8.881784e-016 - vertex 4.342717e+001 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 8.191520e-001 -3.257609e-016 - outer loop - vertex 4.342717e+001 1.514629e+001 -8.881784e-016 - vertex 4.307020e+001 1.489634e+001 -8.881784e-016 - vertex 4.307020e+001 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 9.063078e-001 3.166431e-016 - outer loop - vertex 4.267525e+001 1.471217e+001 -8.881784e-016 - vertex 4.267525e+001 1.471217e+001 4.399139e+000 - vertex 4.307020e+001 1.489634e+001 -8.881784e-016 - endloop - endfacet - facet normal -2.588190e-001 9.659258e-001 0.000000e+000 - outer loop - vertex 4.267525e+001 1.471217e+001 -8.881784e-016 - vertex 4.225432e+001 1.459938e+001 -8.881784e-016 - vertex 4.225432e+001 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 9.961947e-001 0.000000e+000 - outer loop - vertex 4.225432e+001 1.459938e+001 -8.881784e-016 - vertex 4.182020e+001 1.456140e+001 -8.881784e-016 - vertex 4.182020e+001 1.456140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 9.961947e-001 -1.411631e-016 - outer loop - vertex 4.182020e+001 1.456140e+001 -8.881784e-016 - vertex 4.138608e+001 1.459938e+001 -8.881784e-016 - vertex 4.138608e+001 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 9.659258e-001 -4.198697e-016 - outer loop - vertex 4.138608e+001 1.459938e+001 -8.881784e-016 - vertex 4.096515e+001 1.471217e+001 -8.881784e-016 - vertex 4.096515e+001 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 9.063078e-001 3.691957e-016 - outer loop - vertex 4.096515e+001 1.471217e+001 -8.881784e-016 - vertex 4.057020e+001 1.489634e+001 -8.881784e-016 - vertex 4.057020e+001 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 8.191520e-001 3.330001e-016 - outer loop - vertex 4.057020e+001 1.489634e+001 -8.881784e-016 - vertex 4.021323e+001 1.514629e+001 -8.881784e-016 - vertex 4.021323e+001 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 7.071068e-001 2.855272e-016 - outer loop - vertex 3.990509e+001 1.545443e+001 -8.881784e-016 - vertex 3.990509e+001 1.545443e+001 4.399139e+000 - vertex 4.021323e+001 1.514629e+001 -8.881784e-016 - endloop - endfacet - facet normal 8.191520e-001 5.735764e-001 0.000000e+000 - outer loop - vertex 3.990509e+001 1.545443e+001 -8.881784e-016 - vertex 3.965514e+001 1.581140e+001 -8.881784e-016 - vertex 3.965514e+001 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 4.226183e-001 0.000000e+000 - outer loop - vertex 3.965514e+001 1.581140e+001 -8.881784e-016 - vertex 3.947097e+001 1.620635e+001 -8.881784e-016 - vertex 3.947097e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 2.588190e-001 2.090204e-016 - outer loop - vertex 3.935818e+001 1.662728e+001 -8.881784e-016 - vertex 3.935818e+001 1.662728e+001 4.399139e+000 - vertex 3.947097e+001 1.620635e+001 -8.881784e-016 - endloop - endfacet - facet normal 9.961947e-001 8.715574e-002 7.040056e-016 - outer loop - vertex 3.935818e+001 1.662728e+001 -8.881784e-016 - vertex 3.932020e+001 1.706140e+001 -8.881784e-016 - vertex 3.932020e+001 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 -8.715574e-002 9.048915e-016 - outer loop - vertex 3.932020e+001 1.706140e+001 -8.881784e-016 - vertex 3.935818e+001 1.749552e+001 -8.881784e-016 - vertex 3.935818e+001 1.749552e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 -2.588190e-001 1.030095e-015 - outer loop - vertex 3.947097e+001 1.791645e+001 -8.881784e-016 - vertex 3.947097e+001 1.791645e+001 4.399139e+000 - vertex 3.935818e+001 1.749552e+001 -8.881784e-016 - endloop - endfacet - facet normal 9.063078e-001 -4.226183e-001 1.954566e-016 - outer loop - vertex 3.947097e+001 1.791645e+001 -8.881784e-016 - vertex 3.965514e+001 1.831140e+001 -8.881784e-016 - vertex 3.965514e+001 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 -5.735764e-001 2.606088e-016 - outer loop - vertex 3.965514e+001 1.831140e+001 -8.881784e-016 - vertex 3.990509e+001 1.866837e+001 -8.881784e-016 - vertex 3.990509e+001 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 -7.071068e-001 5.710544e-016 - outer loop - vertex 4.021323e+001 1.897651e+001 -8.881784e-016 - vertex 4.021323e+001 1.897651e+001 4.399139e+000 - vertex 3.990509e+001 1.866837e+001 -8.881784e-016 - endloop - endfacet - facet normal 5.735764e-001 -8.191520e-001 3.981523e-016 - outer loop - vertex 4.021323e+001 1.897651e+001 -8.881784e-016 - vertex 4.057020e+001 1.922646e+001 -8.881784e-016 - vertex 4.057020e+001 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 -9.063078e-001 1.216174e-015 - outer loop - vertex 4.057020e+001 1.922646e+001 -8.881784e-016 - vertex 4.096515e+001 1.941063e+001 -8.881784e-016 - vertex 4.096515e+001 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 -9.659258e-001 5.284567e-016 - outer loop - vertex 4.096515e+001 1.941063e+001 -8.881784e-016 - vertex 4.138608e+001 1.952342e+001 -8.881784e-016 - vertex 4.138608e+001 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 - outer loop - vertex 4.138608e+001 1.952342e+001 -8.881784e-016 - vertex 4.182020e+001 1.956140e+001 -8.881784e-016 - vertex 4.182020e+001 1.956140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 -9.961947e-001 1.013479e-016 - outer loop - vertex 4.182020e+001 1.956140e+001 -8.881784e-016 - vertex 4.225432e+001 1.952342e+001 -8.881784e-016 - vertex 4.225432e+001 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 -9.659258e-001 2.497501e-016 - outer loop - vertex 4.225432e+001 1.952342e+001 -8.881784e-016 - vertex 4.267525e+001 1.941063e+001 -8.881784e-016 - vertex 4.267525e+001 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 -9.063078e-001 2.461305e-016 - outer loop - vertex 4.267525e+001 1.941063e+001 -8.881784e-016 - vertex 4.307020e+001 1.922646e+001 -8.881784e-016 - vertex 4.307020e+001 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 -8.191520e-001 2.678479e-016 - outer loop - vertex 4.307020e+001 1.922646e+001 -8.881784e-016 - vertex 4.342717e+001 1.897651e+001 -8.881784e-016 - vertex 4.342717e+001 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 -7.071068e-001 0.000000e+000 - outer loop - vertex 4.342717e+001 1.897651e+001 -8.881784e-016 - vertex 4.373531e+001 1.866837e+001 -8.881784e-016 - vertex 4.373531e+001 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 -5.735764e-001 1.520218e-015 - outer loop - vertex 4.373531e+001 1.866837e+001 -8.881784e-016 - vertex 4.398526e+001 1.831140e+001 -8.881784e-016 - vertex 4.398526e+001 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 -4.226183e-001 4.850219e-016 - outer loop - vertex 4.398526e+001 1.831140e+001 -8.881784e-016 - vertex 4.416943e+001 1.791645e+001 -8.881784e-016 - vertex 4.416943e+001 1.791645e+001 4.399139e+000 - endloop - endfacet - facet normal 5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 2.137337e+001 1.245363e+001 5.000000e+000 - vertex 2.232020e+001 1.306140e+001 4.399139e+000 - vertex 2.132020e+001 1.306140e+001 5.000000e+000 - endloop - endfacet - facet normal 5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 2.137337e+001 1.245363e+001 5.000000e+000 - vertex 2.235818e+001 1.262728e+001 4.399139e+000 - vertex 2.232020e+001 1.306140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 2.137337e+001 1.245363e+001 5.000000e+000 - vertex 2.153128e+001 1.186433e+001 5.000000e+000 - vertex 2.235818e+001 1.262728e+001 4.399139e+000 - endloop - endfacet - facet normal 4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 2.235818e+001 1.262728e+001 4.399139e+000 - vertex 2.153128e+001 1.186433e+001 5.000000e+000 - vertex 2.247097e+001 1.220635e+001 4.399139e+000 - endloop - endfacet - facet normal 4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 2.247097e+001 1.220635e+001 4.399139e+000 - vertex 2.153128e+001 1.186433e+001 5.000000e+000 - vertex 2.178911e+001 1.131140e+001 5.000000e+000 - endloop - endfacet - facet normal 4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 2.265514e+001 1.181140e+001 4.399139e+000 - vertex 2.178911e+001 1.131140e+001 5.000000e+000 - vertex 2.213904e+001 1.081164e+001 5.000000e+000 - endloop - endfacet - facet normal 3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 2.290509e+001 1.145443e+001 4.399139e+000 - vertex 2.213904e+001 1.081164e+001 5.000000e+000 - vertex 2.257044e+001 1.038024e+001 5.000000e+000 - endloop - endfacet - facet normal 2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 2.321323e+001 1.114629e+001 4.399139e+000 - vertex 2.257044e+001 1.038024e+001 5.000000e+000 - vertex 2.307020e+001 1.003031e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 2.357020e+001 1.089634e+001 4.399139e+000 - vertex 2.307020e+001 1.003031e+001 5.000000e+000 - vertex 2.362313e+001 9.772476e+000 5.000000e+000 - endloop - endfacet - facet normal 1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 2.396515e+001 1.071217e+001 4.399139e+000 - vertex 2.362313e+001 9.772476e+000 5.000000e+000 - vertex 2.421243e+001 9.614573e+000 5.000000e+000 - endloop - endfacet - facet normal 4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 2.438608e+001 1.059938e+001 4.399139e+000 - vertex 2.421243e+001 9.614573e+000 5.000000e+000 - vertex 2.482020e+001 1.056140e+001 4.399139e+000 - endloop - endfacet - facet normal 1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 2.438608e+001 1.059938e+001 4.399139e+000 - vertex 2.396515e+001 1.071217e+001 4.399139e+000 - vertex 2.421243e+001 9.614573e+000 5.000000e+000 - endloop - endfacet - facet normal 4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 2.421243e+001 9.614573e+000 5.000000e+000 - vertex 2.482020e+001 9.561400e+000 5.000000e+000 - vertex 2.482020e+001 1.056140e+001 4.399139e+000 - endloop - endfacet - facet normal -4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 2.482020e+001 1.056140e+001 4.399139e+000 - vertex 2.482020e+001 9.561400e+000 5.000000e+000 - vertex 2.542797e+001 9.614573e+000 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 2.525432e+001 1.059938e+001 4.399139e+000 - vertex 2.542797e+001 9.614573e+000 5.000000e+000 - vertex 2.601727e+001 9.772476e+000 5.000000e+000 - endloop - endfacet - facet normal -2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 2.567525e+001 1.071217e+001 4.399139e+000 - vertex 2.601727e+001 9.772476e+000 5.000000e+000 - vertex 2.657020e+001 1.003031e+001 5.000000e+000 - endloop - endfacet - facet normal -2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 2.607020e+001 1.089634e+001 4.399139e+000 - vertex 2.657020e+001 1.003031e+001 5.000000e+000 - vertex 2.642717e+001 1.114629e+001 4.399139e+000 - endloop - endfacet - facet normal -2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 2.607020e+001 1.089634e+001 4.399139e+000 - vertex 2.567525e+001 1.071217e+001 4.399139e+000 - vertex 2.657020e+001 1.003031e+001 5.000000e+000 - endloop - endfacet - facet normal -2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 2.657020e+001 1.003031e+001 5.000000e+000 - vertex 2.706996e+001 1.038024e+001 5.000000e+000 - vertex 2.642717e+001 1.114629e+001 4.399139e+000 - endloop - endfacet - facet normal -3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 2.642717e+001 1.114629e+001 4.399139e+000 - vertex 2.706996e+001 1.038024e+001 5.000000e+000 - vertex 2.750136e+001 1.081164e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 2.673531e+001 1.145443e+001 4.399139e+000 - vertex 2.750136e+001 1.081164e+001 5.000000e+000 - vertex 2.785129e+001 1.131140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 2.698526e+001 1.181140e+001 4.399139e+000 - vertex 2.785129e+001 1.131140e+001 5.000000e+000 - vertex 2.810912e+001 1.186433e+001 5.000000e+000 - endloop - endfacet - facet normal -4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 2.716943e+001 1.220635e+001 4.399139e+000 - vertex 2.810912e+001 1.186433e+001 5.000000e+000 - vertex 2.826703e+001 1.245363e+001 5.000000e+000 - endloop - endfacet - facet normal -5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 2.728222e+001 1.262728e+001 4.399139e+000 - vertex 2.826703e+001 1.245363e+001 5.000000e+000 - vertex 2.832020e+001 1.306140e+001 5.000000e+000 - endloop - endfacet - facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 2.732020e+001 1.306140e+001 4.399139e+000 - vertex 2.832020e+001 1.306140e+001 5.000000e+000 - vertex 2.728222e+001 1.349552e+001 4.399139e+000 - endloop - endfacet - facet normal -5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 2.732020e+001 1.306140e+001 4.399139e+000 - vertex 2.728222e+001 1.262728e+001 4.399139e+000 - vertex 2.832020e+001 1.306140e+001 5.000000e+000 - endloop - endfacet - facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 2.832020e+001 1.306140e+001 5.000000e+000 - vertex 2.826703e+001 1.366917e+001 5.000000e+000 - vertex 2.728222e+001 1.349552e+001 4.399139e+000 - endloop - endfacet - facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 2.728222e+001 1.349552e+001 4.399139e+000 - vertex 2.826703e+001 1.366917e+001 5.000000e+000 - vertex 2.716943e+001 1.391645e+001 4.399139e+000 - endloop - endfacet - facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 2.716943e+001 1.391645e+001 4.399139e+000 - vertex 2.826703e+001 1.366917e+001 5.000000e+000 - vertex 2.810912e+001 1.425847e+001 5.000000e+000 - endloop - endfacet - facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 2.698526e+001 1.431140e+001 4.399139e+000 - vertex 2.810912e+001 1.425847e+001 5.000000e+000 - vertex 2.785129e+001 1.481140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 2.750136e+001 1.531116e+001 5.000000e+000 - vertex 2.698526e+001 1.431140e+001 4.399139e+000 - vertex 2.785129e+001 1.481140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 2.750136e+001 1.531116e+001 5.000000e+000 - vertex 2.673531e+001 1.466837e+001 4.399139e+000 - vertex 2.698526e+001 1.431140e+001 4.399139e+000 - endloop - endfacet - facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 2.750136e+001 1.531116e+001 5.000000e+000 - vertex 2.706996e+001 1.574256e+001 5.000000e+000 - vertex 2.673531e+001 1.466837e+001 4.399139e+000 - endloop - endfacet - facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 2.673531e+001 1.466837e+001 4.399139e+000 - vertex 2.706996e+001 1.574256e+001 5.000000e+000 - vertex 2.642717e+001 1.497651e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 2.642717e+001 1.497651e+001 4.399139e+000 - vertex 2.706996e+001 1.574256e+001 5.000000e+000 - vertex 2.607020e+001 1.522646e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 2.607020e+001 1.522646e+001 4.399139e+000 - vertex 2.706996e+001 1.574256e+001 5.000000e+000 - vertex 2.657020e+001 1.609249e+001 5.000000e+000 - endloop - endfacet - facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 2.567525e+001 1.541063e+001 4.399139e+000 - vertex 2.657020e+001 1.609249e+001 5.000000e+000 - vertex 2.601727e+001 1.635032e+001 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 2.525432e+001 1.552342e+001 4.399139e+000 - vertex 2.601727e+001 1.635032e+001 5.000000e+000 - vertex 2.542797e+001 1.650823e+001 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 2.482020e+001 1.656140e+001 5.000000e+000 - vertex 2.525432e+001 1.552342e+001 4.399139e+000 - vertex 2.542797e+001 1.650823e+001 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 2.482020e+001 1.656140e+001 5.000000e+000 - vertex 2.482020e+001 1.556140e+001 4.399139e+000 - vertex 2.525432e+001 1.552342e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 2.482020e+001 1.656140e+001 5.000000e+000 - vertex 2.421243e+001 1.650823e+001 5.000000e+000 - vertex 2.482020e+001 1.556140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 2.482020e+001 1.556140e+001 4.399139e+000 - vertex 2.421243e+001 1.650823e+001 5.000000e+000 - vertex 2.438608e+001 1.552342e+001 4.399139e+000 - endloop - endfacet - facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 2.438608e+001 1.552342e+001 4.399139e+000 - vertex 2.421243e+001 1.650823e+001 5.000000e+000 - vertex 2.362313e+001 1.635032e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 2.396515e+001 1.541063e+001 4.399139e+000 - vertex 2.362313e+001 1.635032e+001 5.000000e+000 - vertex 2.307020e+001 1.609249e+001 5.000000e+000 - endloop - endfacet - facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 2.357020e+001 1.522646e+001 4.399139e+000 - vertex 2.307020e+001 1.609249e+001 5.000000e+000 - vertex 2.321323e+001 1.497651e+001 4.399139e+000 - endloop - endfacet - facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 2.357020e+001 1.522646e+001 4.399139e+000 - vertex 2.396515e+001 1.541063e+001 4.399139e+000 - vertex 2.307020e+001 1.609249e+001 5.000000e+000 - endloop - endfacet - facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 2.321323e+001 1.497651e+001 4.399139e+000 - vertex 2.307020e+001 1.609249e+001 5.000000e+000 - vertex 2.257044e+001 1.574256e+001 5.000000e+000 - endloop - endfacet - facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 2.213904e+001 1.531116e+001 5.000000e+000 - vertex 2.321323e+001 1.497651e+001 4.399139e+000 - vertex 2.257044e+001 1.574256e+001 5.000000e+000 - endloop - endfacet - facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 2.213904e+001 1.531116e+001 5.000000e+000 - vertex 2.290509e+001 1.466837e+001 4.399139e+000 - vertex 2.321323e+001 1.497651e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 2.213904e+001 1.531116e+001 5.000000e+000 - vertex 2.178911e+001 1.481140e+001 5.000000e+000 - vertex 2.290509e+001 1.466837e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 2.290509e+001 1.466837e+001 4.399139e+000 - vertex 2.178911e+001 1.481140e+001 5.000000e+000 - vertex 2.265514e+001 1.431140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 2.265514e+001 1.431140e+001 4.399139e+000 - vertex 2.178911e+001 1.481140e+001 5.000000e+000 - vertex 2.153128e+001 1.425847e+001 5.000000e+000 - endloop - endfacet - facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 2.247097e+001 1.391645e+001 4.399139e+000 - vertex 2.153128e+001 1.425847e+001 5.000000e+000 - vertex 2.137337e+001 1.366917e+001 5.000000e+000 - endloop - endfacet - facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 2.235818e+001 1.349552e+001 4.399139e+000 - vertex 2.137337e+001 1.366917e+001 5.000000e+000 - vertex 2.132020e+001 1.306140e+001 5.000000e+000 - endloop - endfacet - facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 2.232020e+001 1.306140e+001 4.399139e+000 - vertex 2.235818e+001 1.349552e+001 4.399139e+000 - vertex 2.132020e+001 1.306140e+001 5.000000e+000 - endloop - endfacet - facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 2.235818e+001 1.349552e+001 4.399139e+000 - vertex 2.247097e+001 1.391645e+001 4.399139e+000 - vertex 2.137337e+001 1.366917e+001 5.000000e+000 - endloop - endfacet - facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 2.247097e+001 1.391645e+001 4.399139e+000 - vertex 2.265514e+001 1.431140e+001 4.399139e+000 - vertex 2.153128e+001 1.425847e+001 5.000000e+000 - endloop - endfacet - facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 2.396515e+001 1.541063e+001 4.399139e+000 - vertex 2.438608e+001 1.552342e+001 4.399139e+000 - vertex 2.362313e+001 1.635032e+001 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 2.525432e+001 1.552342e+001 4.399139e+000 - vertex 2.567525e+001 1.541063e+001 4.399139e+000 - vertex 2.601727e+001 1.635032e+001 5.000000e+000 - endloop - endfacet - facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 2.567525e+001 1.541063e+001 4.399139e+000 - vertex 2.607020e+001 1.522646e+001 4.399139e+000 - vertex 2.657020e+001 1.609249e+001 5.000000e+000 - endloop - endfacet - facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 2.698526e+001 1.431140e+001 4.399139e+000 - vertex 2.716943e+001 1.391645e+001 4.399139e+000 - vertex 2.810912e+001 1.425847e+001 5.000000e+000 - endloop - endfacet - facet normal -4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 2.728222e+001 1.262728e+001 4.399139e+000 - vertex 2.716943e+001 1.220635e+001 4.399139e+000 - vertex 2.826703e+001 1.245363e+001 5.000000e+000 - endloop - endfacet - facet normal -4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 2.716943e+001 1.220635e+001 4.399139e+000 - vertex 2.698526e+001 1.181140e+001 4.399139e+000 - vertex 2.810912e+001 1.186433e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 2.698526e+001 1.181140e+001 4.399139e+000 - vertex 2.673531e+001 1.145443e+001 4.399139e+000 - vertex 2.785129e+001 1.131140e+001 5.000000e+000 - endloop - endfacet - facet normal -3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 2.673531e+001 1.145443e+001 4.399139e+000 - vertex 2.642717e+001 1.114629e+001 4.399139e+000 - vertex 2.750136e+001 1.081164e+001 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 2.567525e+001 1.071217e+001 4.399139e+000 - vertex 2.525432e+001 1.059938e+001 4.399139e+000 - vertex 2.601727e+001 9.772476e+000 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 2.525432e+001 1.059938e+001 4.399139e+000 - vertex 2.482020e+001 1.056140e+001 4.399139e+000 - vertex 2.542797e+001 9.614573e+000 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 2.396515e+001 1.071217e+001 4.399139e+000 - vertex 2.357020e+001 1.089634e+001 4.399139e+000 - vertex 2.362313e+001 9.772476e+000 5.000000e+000 - endloop - endfacet - facet normal 2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 2.357020e+001 1.089634e+001 4.399139e+000 - vertex 2.321323e+001 1.114629e+001 4.399139e+000 - vertex 2.307020e+001 1.003031e+001 5.000000e+000 - endloop - endfacet - facet normal 3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 2.321323e+001 1.114629e+001 4.399139e+000 - vertex 2.290509e+001 1.145443e+001 4.399139e+000 - vertex 2.257044e+001 1.038024e+001 5.000000e+000 - endloop - endfacet - facet normal 4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 2.290509e+001 1.145443e+001 4.399139e+000 - vertex 2.265514e+001 1.181140e+001 4.399139e+000 - vertex 2.213904e+001 1.081164e+001 5.000000e+000 - endloop - endfacet - facet normal 4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 2.265514e+001 1.181140e+001 4.399139e+000 - vertex 2.247097e+001 1.220635e+001 4.399139e+000 - vertex 2.178911e+001 1.131140e+001 5.000000e+000 - endloop - endfacet - facet normal -9.961947e-001 8.715574e-002 -3.438588e-017 - outer loop - vertex 2.732020e+001 1.306140e+001 0.000000e+000 - vertex 2.728222e+001 1.262728e+001 0.000000e+000 - vertex 2.728222e+001 1.262728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.961947e-001 8.715574e-002 0.000000e+000 - outer loop - vertex 2.732020e+001 1.306140e+001 4.399139e+000 - vertex 2.732020e+001 1.306140e+001 0.000000e+000 - vertex 2.728222e+001 1.262728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 - outer loop - vertex 2.732020e+001 1.306140e+001 4.399139e+000 - vertex 2.728222e+001 1.349552e+001 0.000000e+000 - vertex 2.732020e+001 1.306140e+001 0.000000e+000 - endloop - endfacet - facet normal -9.961947e-001 -8.715574e-002 -6.515219e-017 - outer loop - vertex 2.732020e+001 1.306140e+001 4.399139e+000 - vertex 2.728222e+001 1.349552e+001 4.399139e+000 - vertex 2.728222e+001 1.349552e+001 0.000000e+000 - endloop - endfacet - facet normal -9.659258e-001 -2.588190e-001 1.414640e-015 - outer loop - vertex 2.728222e+001 1.349552e+001 0.000000e+000 - vertex 2.728222e+001 1.349552e+001 4.399139e+000 - vertex 2.716943e+001 1.391645e+001 0.000000e+000 - endloop - endfacet - facet normal -9.659258e-001 -2.588190e-001 -3.545305e-016 - outer loop - vertex 2.716943e+001 1.391645e+001 0.000000e+000 - vertex 2.728222e+001 1.349552e+001 4.399139e+000 - vertex 2.716943e+001 1.391645e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 -4.226183e-001 -7.585588e-016 - outer loop - vertex 2.698526e+001 1.431140e+001 0.000000e+000 - vertex 2.716943e+001 1.391645e+001 4.399139e+000 - vertex 2.698526e+001 1.431140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 -5.735764e-001 -2.635182e-016 - outer loop - vertex 2.673531e+001 1.466837e+001 0.000000e+000 - vertex 2.698526e+001 1.431140e+001 4.399139e+000 - vertex 2.673531e+001 1.466837e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 -7.071068e-001 -5.710544e-016 - outer loop - vertex 2.642717e+001 1.497651e+001 0.000000e+000 - vertex 2.673531e+001 1.466837e+001 4.399139e+000 - vertex 2.642717e+001 1.497651e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 -8.191520e-001 -8.612394e-016 - outer loop - vertex 2.607020e+001 1.522646e+001 0.000000e+000 - vertex 2.642717e+001 1.497651e+001 4.399139e+000 - vertex 2.607020e+001 1.522646e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 -9.063078e-001 -4.853241e-016 - outer loop - vertex 2.567525e+001 1.541063e+001 0.000000e+000 - vertex 2.607020e+001 1.522646e+001 4.399139e+000 - vertex 2.567525e+001 1.541063e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 -9.659258e-001 -5.300545e-016 - outer loop - vertex 2.525432e+001 1.552342e+001 0.000000e+000 - vertex 2.567525e+001 1.541063e+001 4.399139e+000 - vertex 2.525432e+001 1.552342e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 - outer loop - vertex 2.482020e+001 1.556140e+001 0.000000e+000 - vertex 2.525432e+001 1.552342e+001 4.399139e+000 - vertex 2.482020e+001 1.556140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 -9.961947e-001 -5.029161e-016 - outer loop - vertex 2.438608e+001 1.552342e+001 0.000000e+000 - vertex 2.482020e+001 1.556140e+001 4.399139e+000 - vertex 2.438608e+001 1.552342e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 -9.659258e-001 -6.400577e-016 - outer loop - vertex 2.396515e+001 1.541063e+001 0.000000e+000 - vertex 2.438608e+001 1.552342e+001 4.399139e+000 - vertex 2.396515e+001 1.541063e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 -9.063078e-001 -5.879071e-016 - outer loop - vertex 2.357020e+001 1.522646e+001 0.000000e+000 - vertex 2.396515e+001 1.541063e+001 4.399139e+000 - vertex 2.357020e+001 1.522646e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 -8.191520e-001 -5.942889e-016 - outer loop - vertex 2.321323e+001 1.497651e+001 0.000000e+000 - vertex 2.357020e+001 1.522646e+001 4.399139e+000 - vertex 2.321323e+001 1.497651e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 -7.071068e-001 -5.710544e-016 - outer loop - vertex 2.290509e+001 1.466837e+001 0.000000e+000 - vertex 2.321323e+001 1.497651e+001 4.399139e+000 - vertex 2.290509e+001 1.466837e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 -5.735764e-001 -8.612394e-016 - outer loop - vertex 2.265514e+001 1.431140e+001 0.000000e+000 - vertex 2.290509e+001 1.466837e+001 4.399139e+000 - vertex 2.265514e+001 1.431140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 -4.226183e-001 -3.146724e-016 - outer loop - vertex 2.247097e+001 1.391645e+001 0.000000e+000 - vertex 2.265514e+001 1.431140e+001 4.399139e+000 - vertex 2.247097e+001 1.391645e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 -2.588190e-001 -5.300545e-016 - outer loop - vertex 2.235818e+001 1.349552e+001 0.000000e+000 - vertex 2.247097e+001 1.391645e+001 4.399139e+000 - vertex 2.235818e+001 1.349552e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 - outer loop - vertex 2.232020e+001 1.306140e+001 0.000000e+000 - vertex 2.235818e+001 1.349552e+001 4.399139e+000 - vertex 2.232020e+001 1.306140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 8.715574e-002 3.519318e-017 - outer loop - vertex 2.235818e+001 1.262728e+001 0.000000e+000 - vertex 2.232020e+001 1.306140e+001 4.399139e+000 - vertex 2.235818e+001 1.262728e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 2.588190e-001 -5.710544e-016 - outer loop - vertex 2.247097e+001 1.220635e+001 0.000000e+000 - vertex 2.235818e+001 1.262728e+001 4.399139e+000 - vertex 2.247097e+001 1.220635e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 4.226183e-001 1.706518e-016 - outer loop - vertex 2.265514e+001 1.181140e+001 0.000000e+000 - vertex 2.247097e+001 1.220635e+001 4.399139e+000 - vertex 2.265514e+001 1.181140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 5.735764e-001 2.316081e-016 - outer loop - vertex 2.290509e+001 1.145443e+001 0.000000e+000 - vertex 2.265514e+001 1.181140e+001 4.399139e+000 - vertex 2.290509e+001 1.145443e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 7.071068e-001 -2.855272e-016 - outer loop - vertex 2.321323e+001 1.114629e+001 0.000000e+000 - vertex 2.290509e+001 1.145443e+001 4.399139e+000 - vertex 2.321323e+001 1.114629e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 8.191520e-001 0.000000e+000 - outer loop - vertex 2.357020e+001 1.089634e+001 0.000000e+000 - vertex 2.321323e+001 1.114629e+001 4.399139e+000 - vertex 2.357020e+001 1.089634e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 9.063078e-001 -3.413035e-016 - outer loop - vertex 2.396515e+001 1.071217e+001 0.000000e+000 - vertex 2.357020e+001 1.089634e+001 4.399139e+000 - vertex 2.396515e+001 1.071217e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 9.659258e-001 -2.090204e-016 - outer loop - vertex 2.438608e+001 1.059938e+001 0.000000e+000 - vertex 2.396515e+001 1.071217e+001 4.399139e+000 - vertex 2.438608e+001 1.059938e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 9.961947e-001 -7.038636e-017 - outer loop - vertex 2.482020e+001 1.056140e+001 0.000000e+000 - vertex 2.438608e+001 1.059938e+001 4.399139e+000 - vertex 2.482020e+001 1.056140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 9.961947e-001 -3.318735e-016 - outer loop - vertex 2.525432e+001 1.059938e+001 0.000000e+000 - vertex 2.482020e+001 1.056140e+001 4.399139e+000 - vertex 2.525432e+001 1.059938e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 9.659258e-001 2.090204e-016 - outer loop - vertex 2.567525e+001 1.071217e+001 0.000000e+000 - vertex 2.525432e+001 1.059938e+001 4.399139e+000 - vertex 2.567525e+001 1.071217e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 9.063078e-001 0.000000e+000 - outer loop - vertex 2.607020e+001 1.089634e+001 0.000000e+000 - vertex 2.567525e+001 1.071217e+001 4.399139e+000 - vertex 2.607020e+001 1.089634e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 8.191520e-001 1.324456e-016 - outer loop - vertex 2.642717e+001 1.114629e+001 0.000000e+000 - vertex 2.607020e+001 1.089634e+001 4.399139e+000 - vertex 2.642717e+001 1.114629e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 7.071068e-001 5.710544e-016 - outer loop - vertex 2.673531e+001 1.145443e+001 0.000000e+000 - vertex 2.642717e+001 1.114629e+001 4.399139e+000 - vertex 2.673531e+001 1.145443e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 5.735764e-001 0.000000e+000 - outer loop - vertex 2.698526e+001 1.181140e+001 0.000000e+000 - vertex 2.673531e+001 1.145443e+001 4.399139e+000 - vertex 2.698526e+001 1.181140e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 4.226183e-001 -3.413035e-016 - outer loop - vertex 2.716943e+001 1.220635e+001 0.000000e+000 - vertex 2.698526e+001 1.181140e+001 4.399139e+000 - vertex 2.716943e+001 1.220635e+001 4.399139e+000 - endloop - endfacet - facet normal -9.659258e-001 2.588190e-001 -1.045102e-016 - outer loop - vertex 2.728222e+001 1.262728e+001 0.000000e+000 - vertex 2.716943e+001 1.220635e+001 4.399139e+000 - vertex 2.728222e+001 1.262728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.659258e-001 2.588190e-001 -2.063153e-016 - outer loop - vertex 2.728222e+001 1.262728e+001 0.000000e+000 - vertex 2.716943e+001 1.220635e+001 0.000000e+000 - vertex 2.716943e+001 1.220635e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 4.226183e-001 0.000000e+000 - outer loop - vertex 2.716943e+001 1.220635e+001 0.000000e+000 - vertex 2.698526e+001 1.181140e+001 0.000000e+000 - vertex 2.698526e+001 1.181140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 5.735764e-001 6.587610e-016 - outer loop - vertex 2.698526e+001 1.181140e+001 0.000000e+000 - vertex 2.673531e+001 1.145443e+001 0.000000e+000 - vertex 2.673531e+001 1.145443e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 7.071068e-001 2.895653e-016 - outer loop - vertex 2.673531e+001 1.145443e+001 0.000000e+000 - vertex 2.642717e+001 1.114629e+001 0.000000e+000 - vertex 2.642717e+001 1.114629e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 8.191520e-001 0.000000e+000 - outer loop - vertex 2.642717e+001 1.114629e+001 0.000000e+000 - vertex 2.607020e+001 1.089634e+001 0.000000e+000 - vertex 2.607020e+001 1.089634e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 9.063078e-001 3.402392e-016 - outer loop - vertex 2.607020e+001 1.089634e+001 0.000000e+000 - vertex 2.567525e+001 1.071217e+001 0.000000e+000 - vertex 2.567525e+001 1.071217e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 9.659258e-001 -1.845979e-016 - outer loop - vertex 2.567525e+001 1.071217e+001 0.000000e+000 - vertex 2.525432e+001 1.059938e+001 0.000000e+000 - vertex 2.525432e+001 1.059938e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 9.961947e-001 7.058154e-017 - outer loop - vertex 2.525432e+001 1.059938e+001 0.000000e+000 - vertex 2.482020e+001 1.056140e+001 0.000000e+000 - vertex 2.482020e+001 1.056140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 9.961947e-001 -7.058154e-017 - outer loop - vertex 2.482020e+001 1.056140e+001 0.000000e+000 - vertex 2.438608e+001 1.059938e+001 0.000000e+000 - vertex 2.438608e+001 1.059938e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 9.659258e-001 -2.099348e-016 - outer loop - vertex 2.438608e+001 1.059938e+001 0.000000e+000 - vertex 2.396515e+001 1.071217e+001 0.000000e+000 - vertex 2.396515e+001 1.071217e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 9.063078e-001 0.000000e+000 - outer loop - vertex 2.396515e+001 1.071217e+001 0.000000e+000 - vertex 2.357020e+001 1.089634e+001 0.000000e+000 - vertex 2.357020e+001 1.089634e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 8.191520e-001 -1.303044e-016 - outer loop - vertex 2.357020e+001 1.089634e+001 0.000000e+000 - vertex 2.321323e+001 1.114629e+001 0.000000e+000 - vertex 2.321323e+001 1.114629e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 7.071068e-001 2.895653e-016 - outer loop - vertex 2.321323e+001 1.114629e+001 0.000000e+000 - vertex 2.290509e+001 1.145443e+001 0.000000e+000 - vertex 2.290509e+001 1.145443e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 5.735764e-001 2.316522e-016 - outer loop - vertex 2.290509e+001 1.145443e+001 0.000000e+000 - vertex 2.265514e+001 1.181140e+001 0.000000e+000 - vertex 2.265514e+001 1.181140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 4.226183e-001 -3.909131e-016 - outer loop - vertex 2.265514e+001 1.181140e+001 0.000000e+000 - vertex 2.247097e+001 1.220635e+001 0.000000e+000 - vertex 2.247097e+001 1.220635e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 2.588190e-001 1.049674e-016 - outer loop - vertex 2.247097e+001 1.220635e+001 0.000000e+000 - vertex 2.235818e+001 1.262728e+001 0.000000e+000 - vertex 2.235818e+001 1.262728e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 8.715574e-002 7.040056e-016 - outer loop - vertex 2.235818e+001 1.262728e+001 0.000000e+000 - vertex 2.232020e+001 1.306140e+001 0.000000e+000 - vertex 2.232020e+001 1.306140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 -8.715574e-002 9.048915e-016 - outer loop - vertex 2.232020e+001 1.306140e+001 0.000000e+000 - vertex 2.235818e+001 1.349552e+001 0.000000e+000 - vertex 2.235818e+001 1.349552e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 -2.588190e-001 1.134605e-015 - outer loop - vertex 2.247097e+001 1.391645e+001 0.000000e+000 - vertex 2.247097e+001 1.391645e+001 4.399139e+000 - vertex 2.235818e+001 1.349552e+001 0.000000e+000 - endloop - endfacet - facet normal 9.063078e-001 -4.226183e-001 5.863697e-016 - outer loop - vertex 2.247097e+001 1.391645e+001 0.000000e+000 - vertex 2.265514e+001 1.431140e+001 0.000000e+000 - vertex 2.265514e+001 1.431140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 -5.735764e-001 9.266089e-016 - outer loop - vertex 2.265514e+001 1.431140e+001 0.000000e+000 - vertex 2.290509e+001 1.466837e+001 0.000000e+000 - vertex 2.290509e+001 1.466837e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 -7.071068e-001 8.542176e-016 - outer loop - vertex 2.290509e+001 1.466837e+001 0.000000e+000 - vertex 2.321323e+001 1.497651e+001 0.000000e+000 - vertex 2.321323e+001 1.497651e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 -8.191520e-001 8.612394e-016 - outer loop - vertex 2.357020e+001 1.522646e+001 0.000000e+000 - vertex 2.357020e+001 1.522646e+001 4.399139e+000 - vertex 2.321323e+001 1.497651e+001 0.000000e+000 - endloop - endfacet - facet normal 4.226183e-001 -9.063078e-001 8.542176e-016 - outer loop - vertex 2.357020e+001 1.522646e+001 0.000000e+000 - vertex 2.396515e+001 1.541063e+001 0.000000e+000 - vertex 2.396515e+001 1.541063e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 -9.659258e-001 9.193698e-016 - outer loop - vertex 2.396515e+001 1.541063e+001 0.000000e+000 - vertex 2.438608e+001 1.552342e+001 0.000000e+000 - vertex 2.438608e+001 1.552342e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 - outer loop - vertex 2.438608e+001 1.552342e+001 0.000000e+000 - vertex 2.482020e+001 1.556140e+001 0.000000e+000 - vertex 2.482020e+001 1.556140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 -9.961947e-001 9.051759e-016 - outer loop - vertex 2.525432e+001 1.552342e+001 0.000000e+000 - vertex 2.525432e+001 1.552342e+001 4.399139e+000 - vertex 2.482020e+001 1.556140e+001 0.000000e+000 - endloop - endfacet - facet normal -2.588190e-001 -9.659258e-001 1.031576e-015 - outer loop - vertex 2.525432e+001 1.552342e+001 0.000000e+000 - vertex 2.567525e+001 1.541063e+001 0.000000e+000 - vertex 2.567525e+001 1.541063e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 -9.063078e-001 5.863697e-016 - outer loop - vertex 2.567525e+001 1.541063e+001 0.000000e+000 - vertex 2.607020e+001 1.522646e+001 0.000000e+000 - vertex 2.607020e+001 1.522646e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 -8.191520e-001 9.266089e-016 - outer loop - vertex 2.607020e+001 1.522646e+001 0.000000e+000 - vertex 2.642717e+001 1.497651e+001 0.000000e+000 - vertex 2.642717e+001 1.497651e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 -7.071068e-001 1.143783e-015 - outer loop - vertex 2.642717e+001 1.497651e+001 0.000000e+000 - vertex 2.673531e+001 1.466837e+001 0.000000e+000 - vertex 2.673531e+001 1.466837e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 -5.735764e-001 6.298045e-016 - outer loop - vertex 2.673531e+001 1.466837e+001 0.000000e+000 - vertex 2.698526e+001 1.431140e+001 0.000000e+000 - vertex 2.698526e+001 1.431140e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 -4.226183e-001 1.049674e-015 - outer loop - vertex 2.698526e+001 1.431140e+001 0.000000e+000 - vertex 2.716943e+001 1.391645e+001 0.000000e+000 - vertex 2.716943e+001 1.391645e+001 4.399139e+000 - endloop - endfacet - facet normal 5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 4.320200e+000 1.706140e+001 5.000000e+000 - vertex 4.373373e+000 1.645363e+001 5.000000e+000 - vertex 5.320200e+000 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 5.358181e+000 1.749552e+001 4.399139e+000 - vertex 4.320200e+000 1.706140e+001 5.000000e+000 - vertex 5.320200e+000 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal 5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 5.358181e+000 1.749552e+001 4.399139e+000 - vertex 4.373373e+000 1.766917e+001 5.000000e+000 - vertex 4.320200e+000 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 5.358181e+000 1.749552e+001 4.399139e+000 - vertex 4.531276e+000 1.825847e+001 5.000000e+000 - vertex 4.373373e+000 1.766917e+001 5.000000e+000 - endloop - endfacet - facet normal 4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 5.358181e+000 1.749552e+001 4.399139e+000 - vertex 5.470968e+000 1.791645e+001 4.399139e+000 - vertex 4.531276e+000 1.825847e+001 5.000000e+000 - endloop - endfacet - facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 4.531276e+000 1.825847e+001 5.000000e+000 - vertex 5.470968e+000 1.791645e+001 4.399139e+000 - vertex 4.789111e+000 1.881140e+001 5.000000e+000 - endloop - endfacet - facet normal 4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 4.789111e+000 1.881140e+001 5.000000e+000 - vertex 5.470968e+000 1.791645e+001 4.399139e+000 - vertex 5.655136e+000 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 5.139044e+000 1.931116e+001 5.000000e+000 - vertex 5.655136e+000 1.831140e+001 4.399139e+000 - vertex 5.905089e+000 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 5.570443e+000 1.974256e+001 5.000000e+000 - vertex 5.905089e+000 1.866837e+001 4.399139e+000 - vertex 6.213231e+000 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 6.570200e+000 1.922646e+001 4.399139e+000 - vertex 5.570443e+000 1.974256e+001 5.000000e+000 - vertex 6.213231e+000 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal 2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 6.570200e+000 1.922646e+001 4.399139e+000 - vertex 6.070200e+000 2.009249e+001 5.000000e+000 - vertex 5.570443e+000 1.974256e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 6.570200e+000 1.922646e+001 4.399139e+000 - vertex 6.965150e+000 1.941063e+001 4.399139e+000 - vertex 6.070200e+000 2.009249e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 6.070200e+000 2.009249e+001 5.000000e+000 - vertex 6.965150e+000 1.941063e+001 4.399139e+000 - vertex 6.623129e+000 2.035032e+001 5.000000e+000 - endloop - endfacet - facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 6.623129e+000 2.035032e+001 5.000000e+000 - vertex 6.965150e+000 1.941063e+001 4.399139e+000 - vertex 7.212431e+000 2.050823e+001 5.000000e+000 - endloop - endfacet - facet normal 1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 7.212431e+000 2.050823e+001 5.000000e+000 - vertex 6.965150e+000 1.941063e+001 4.399139e+000 - vertex 7.386080e+000 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 7.820200e+000 2.056140e+001 5.000000e+000 - vertex 7.386080e+000 1.952342e+001 4.399139e+000 - vertex 7.820200e+000 1.956140e+001 4.399139e+000 - endloop - endfacet - facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 8.427969e+000 2.050823e+001 5.000000e+000 - vertex 7.820200e+000 1.956140e+001 4.399139e+000 - vertex 8.254320e+000 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 9.017271e+000 2.035032e+001 5.000000e+000 - vertex 8.254320e+000 1.952342e+001 4.399139e+000 - vertex 8.675250e+000 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 9.570200e+000 2.009249e+001 5.000000e+000 - vertex 8.675250e+000 1.941063e+001 4.399139e+000 - vertex 9.070200e+000 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 1.006996e+001 1.974256e+001 5.000000e+000 - vertex 9.070200e+000 1.922646e+001 4.399139e+000 - vertex 9.427169e+000 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 9.735311e+000 1.866837e+001 4.399139e+000 - vertex 1.006996e+001 1.974256e+001 5.000000e+000 - vertex 9.427169e+000 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal -3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 9.735311e+000 1.866837e+001 4.399139e+000 - vertex 1.050136e+001 1.931116e+001 5.000000e+000 - vertex 1.006996e+001 1.974256e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 9.735311e+000 1.866837e+001 4.399139e+000 - vertex 9.985264e+000 1.831140e+001 4.399139e+000 - vertex 1.050136e+001 1.931116e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 1.050136e+001 1.931116e+001 5.000000e+000 - vertex 9.985264e+000 1.831140e+001 4.399139e+000 - vertex 1.085129e+001 1.881140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 1.085129e+001 1.881140e+001 5.000000e+000 - vertex 9.985264e+000 1.831140e+001 4.399139e+000 - vertex 1.016943e+001 1.791645e+001 4.399139e+000 - endloop - endfacet - facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 1.110912e+001 1.825847e+001 5.000000e+000 - vertex 1.016943e+001 1.791645e+001 4.399139e+000 - vertex 1.028222e+001 1.749552e+001 4.399139e+000 - endloop - endfacet - facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 1.126703e+001 1.766917e+001 5.000000e+000 - vertex 1.028222e+001 1.749552e+001 4.399139e+000 - vertex 1.132020e+001 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.988827e-001 -1.336752e-001 8.562984e-001 - outer loop - vertex 1.126703e+001 1.766917e+001 5.000000e+000 - vertex 1.110912e+001 1.825847e+001 5.000000e+000 - vertex 1.028222e+001 1.749552e+001 4.399139e+000 - endloop - endfacet - facet normal 4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 4.531276e+000 1.586433e+001 5.000000e+000 - vertex 5.470968e+000 1.620635e+001 4.399139e+000 - vertex 4.373373e+000 1.645363e+001 5.000000e+000 - endloop - endfacet - facet normal 4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 4.531276e+000 1.586433e+001 5.000000e+000 - vertex 5.655136e+000 1.581140e+001 4.399139e+000 - vertex 5.470968e+000 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal 4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 4.531276e+000 1.586433e+001 5.000000e+000 - vertex 4.789111e+000 1.531140e+001 5.000000e+000 - vertex 5.655136e+000 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 5.655136e+000 1.581140e+001 4.399139e+000 - vertex 4.789111e+000 1.531140e+001 5.000000e+000 - vertex 5.905089e+000 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal 4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 5.905089e+000 1.545443e+001 4.399139e+000 - vertex 4.789111e+000 1.531140e+001 5.000000e+000 - vertex 5.139044e+000 1.481164e+001 5.000000e+000 - endloop - endfacet - facet normal 3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 6.213231e+000 1.514629e+001 4.399139e+000 - vertex 5.139044e+000 1.481164e+001 5.000000e+000 - vertex 5.570443e+000 1.438024e+001 5.000000e+000 - endloop - endfacet - facet normal 2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 6.570200e+000 1.489634e+001 4.399139e+000 - vertex 5.570443e+000 1.438024e+001 5.000000e+000 - vertex 6.070200e+000 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 6.623129e+000 1.377248e+001 5.000000e+000 - vertex 6.570200e+000 1.489634e+001 4.399139e+000 - vertex 6.070200e+000 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal 2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 6.623129e+000 1.377248e+001 5.000000e+000 - vertex 6.965150e+000 1.471217e+001 4.399139e+000 - vertex 6.570200e+000 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal 1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 6.623129e+000 1.377248e+001 5.000000e+000 - vertex 7.386080e+000 1.459938e+001 4.399139e+000 - vertex 6.965150e+000 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal 1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 6.623129e+000 1.377248e+001 5.000000e+000 - vertex 7.212431e+000 1.361457e+001 5.000000e+000 - vertex 7.386080e+000 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 7.386080e+000 1.459938e+001 4.399139e+000 - vertex 7.212431e+000 1.361457e+001 5.000000e+000 - vertex 7.820200e+000 1.356140e+001 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 7.820200e+000 1.456140e+001 4.399139e+000 - vertex 7.820200e+000 1.356140e+001 5.000000e+000 - vertex 8.427969e+000 1.361457e+001 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 8.254320e+000 1.459938e+001 4.399139e+000 - vertex 8.427969e+000 1.361457e+001 5.000000e+000 - vertex 9.017271e+000 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal -2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 8.675250e+000 1.471217e+001 4.399139e+000 - vertex 9.017271e+000 1.377248e+001 5.000000e+000 - vertex 9.570200e+000 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal -2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 9.070200e+000 1.489634e+001 4.399139e+000 - vertex 9.570200e+000 1.403031e+001 5.000000e+000 - vertex 1.006996e+001 1.438024e+001 5.000000e+000 - endloop - endfacet - facet normal -3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 9.427169e+000 1.514629e+001 4.399139e+000 - vertex 1.006996e+001 1.438024e+001 5.000000e+000 - vertex 1.050136e+001 1.481164e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 9.735311e+000 1.545443e+001 4.399139e+000 - vertex 1.050136e+001 1.481164e+001 5.000000e+000 - vertex 9.985264e+000 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal -3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 9.735311e+000 1.545443e+001 4.399139e+000 - vertex 9.427169e+000 1.514629e+001 4.399139e+000 - vertex 1.050136e+001 1.481164e+001 5.000000e+000 - endloop - endfacet - facet normal -4.230768e-001 2.962415e-001 8.562984e-001 - outer loop - vertex 1.050136e+001 1.481164e+001 5.000000e+000 - vertex 1.085129e+001 1.531140e+001 5.000000e+000 - vertex 9.985264e+000 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal -4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 9.985264e+000 1.581140e+001 4.399139e+000 - vertex 1.085129e+001 1.531140e+001 5.000000e+000 - vertex 1.016943e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal -4.680911e-001 2.182745e-001 8.562984e-001 - outer loop - vertex 1.016943e+001 1.620635e+001 4.399139e+000 - vertex 1.085129e+001 1.531140e+001 5.000000e+000 - vertex 1.110912e+001 1.586433e+001 5.000000e+000 - endloop - endfacet - facet normal -4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 1.126703e+001 1.645363e+001 5.000000e+000 - vertex 1.016943e+001 1.620635e+001 4.399139e+000 - vertex 1.110912e+001 1.586433e+001 5.000000e+000 - endloop - endfacet - facet normal -4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 1.126703e+001 1.645363e+001 5.000000e+000 - vertex 1.028222e+001 1.662728e+001 4.399139e+000 - vertex 1.016943e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal -5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 1.126703e+001 1.645363e+001 5.000000e+000 - vertex 1.132020e+001 1.706140e+001 5.000000e+000 - vertex 1.028222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 1.028222e+001 1.662728e+001 4.399139e+000 - vertex 1.132020e+001 1.706140e+001 5.000000e+000 - vertex 1.032020e+001 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal -5.145160e-001 -4.501432e-002 8.562984e-001 - outer loop - vertex 1.032020e+001 1.706140e+001 4.399139e+000 - vertex 1.132020e+001 1.706140e+001 5.000000e+000 - vertex 1.028222e+001 1.749552e+001 4.399139e+000 - endloop - endfacet - facet normal -4.680911e-001 -2.182745e-001 8.562984e-001 - outer loop - vertex 1.110912e+001 1.825847e+001 5.000000e+000 - vertex 1.085129e+001 1.881140e+001 5.000000e+000 - vertex 1.016943e+001 1.791645e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 -4.230768e-001 8.562984e-001 - outer loop - vertex 9.070200e+000 1.922646e+001 4.399139e+000 - vertex 1.006996e+001 1.974256e+001 5.000000e+000 - vertex 9.570200e+000 2.009249e+001 5.000000e+000 - endloop - endfacet - facet normal -2.182745e-001 -4.680911e-001 8.562984e-001 - outer loop - vertex 9.017271e+000 2.035032e+001 5.000000e+000 - vertex 8.675250e+000 1.941063e+001 4.399139e+000 - vertex 9.570200e+000 2.009249e+001 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 -4.988827e-001 8.562984e-001 - outer loop - vertex 9.017271e+000 2.035032e+001 5.000000e+000 - vertex 8.427969e+000 2.050823e+001 5.000000e+000 - vertex 8.254320e+000 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal -4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 8.427969e+000 2.050823e+001 5.000000e+000 - vertex 7.820200e+000 2.056140e+001 5.000000e+000 - vertex 7.820200e+000 1.956140e+001 4.399139e+000 - endloop - endfacet - facet normal 4.501432e-002 -5.145160e-001 8.562984e-001 - outer loop - vertex 7.386080e+000 1.952342e+001 4.399139e+000 - vertex 7.820200e+000 2.056140e+001 5.000000e+000 - vertex 7.212431e+000 2.050823e+001 5.000000e+000 - endloop - endfacet - facet normal 3.652075e-001 -3.652075e-001 8.562984e-001 - outer loop - vertex 5.139044e+000 1.931116e+001 5.000000e+000 - vertex 5.905089e+000 1.866837e+001 4.399139e+000 - vertex 5.570443e+000 1.974256e+001 5.000000e+000 - endloop - endfacet - facet normal 4.230768e-001 -2.962415e-001 8.562984e-001 - outer loop - vertex 5.139044e+000 1.931116e+001 5.000000e+000 - vertex 4.789111e+000 1.881140e+001 5.000000e+000 - vertex 5.655136e+000 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal -2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 1.006996e+001 1.438024e+001 5.000000e+000 - vertex 9.427169e+000 1.514629e+001 4.399139e+000 - vertex 9.070200e+000 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal -2.182745e-001 4.680911e-001 8.562984e-001 - outer loop - vertex 9.070200e+000 1.489634e+001 4.399139e+000 - vertex 8.675250e+000 1.471217e+001 4.399139e+000 - vertex 9.570200e+000 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal -1.336752e-001 4.988827e-001 8.562984e-001 - outer loop - vertex 8.675250e+000 1.471217e+001 4.399139e+000 - vertex 8.254320e+000 1.459938e+001 4.399139e+000 - vertex 9.017271e+000 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal -4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 8.254320e+000 1.459938e+001 4.399139e+000 - vertex 7.820200e+000 1.456140e+001 4.399139e+000 - vertex 8.427969e+000 1.361457e+001 5.000000e+000 - endloop - endfacet - facet normal 4.501432e-002 5.145160e-001 8.562984e-001 - outer loop - vertex 7.820200e+000 1.456140e+001 4.399139e+000 - vertex 7.386080e+000 1.459938e+001 4.399139e+000 - vertex 7.820200e+000 1.356140e+001 5.000000e+000 - endloop - endfacet - facet normal 2.962415e-001 4.230768e-001 8.562984e-001 - outer loop - vertex 6.570200e+000 1.489634e+001 4.399139e+000 - vertex 6.213231e+000 1.514629e+001 4.399139e+000 - vertex 5.570443e+000 1.438024e+001 5.000000e+000 - endloop - endfacet - facet normal 3.652075e-001 3.652075e-001 8.562984e-001 - outer loop - vertex 5.139044e+000 1.481164e+001 5.000000e+000 - vertex 6.213231e+000 1.514629e+001 4.399139e+000 - vertex 5.905089e+000 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal 4.988827e-001 1.336752e-001 8.562984e-001 - outer loop - vertex 5.358181e+000 1.662728e+001 4.399139e+000 - vertex 4.373373e+000 1.645363e+001 5.000000e+000 - vertex 5.470968e+000 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal 5.145160e-001 4.501432e-002 8.562984e-001 - outer loop - vertex 5.358181e+000 1.662728e+001 4.399139e+000 - vertex 5.320200e+000 1.706140e+001 4.399139e+000 - vertex 4.373373e+000 1.645363e+001 5.000000e+000 - endloop - endfacet - facet normal -9.961947e-001 8.715574e-002 0.000000e+000 - outer loop - vertex 1.032020e+001 1.706140e+001 -8.881784e-016 - vertex 1.028222e+001 1.662728e+001 -8.881784e-016 - vertex 1.028222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.961947e-001 8.715574e-002 0.000000e+000 - outer loop - vertex 1.032020e+001 1.706140e+001 4.399139e+000 - vertex 1.032020e+001 1.706140e+001 -8.881784e-016 - vertex 1.028222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.961947e-001 -8.715574e-002 0.000000e+000 - outer loop - vertex 1.032020e+001 1.706140e+001 4.399139e+000 - vertex 1.028222e+001 1.749552e+001 -8.881784e-016 - vertex 1.032020e+001 1.706140e+001 -8.881784e-016 - endloop - endfacet - facet normal -9.961947e-001 -8.715574e-002 -9.067013e-016 - outer loop - vertex 1.032020e+001 1.706140e+001 4.399139e+000 - vertex 1.028222e+001 1.749552e+001 4.399139e+000 - vertex 1.028222e+001 1.749552e+001 -8.881784e-016 - endloop - endfacet - facet normal -9.659258e-001 -2.588190e-001 5.300545e-016 - outer loop - vertex 1.028222e+001 1.749552e+001 -8.881784e-016 - vertex 1.028222e+001 1.749552e+001 4.399139e+000 - vertex 1.016943e+001 1.791645e+001 -8.881784e-016 - endloop - endfacet - facet normal -9.659258e-001 -2.588190e-001 -6.400577e-016 - outer loop - vertex 1.016943e+001 1.791645e+001 -8.881784e-016 - vertex 1.028222e+001 1.749552e+001 4.399139e+000 - vertex 1.016943e+001 1.791645e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 -4.226183e-001 -5.879071e-016 - outer loop - vertex 9.985264e+000 1.831140e+001 -8.881784e-016 - vertex 1.016943e+001 1.791645e+001 4.399139e+000 - vertex 9.985264e+000 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 -5.735764e-001 -5.942889e-016 - outer loop - vertex 9.735311e+000 1.866837e+001 -8.881784e-016 - vertex 9.985264e+000 1.831140e+001 4.399139e+000 - vertex 9.735311e+000 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 -7.071068e-001 -1.142109e-015 - outer loop - vertex 9.427169e+000 1.897651e+001 -8.881784e-016 - vertex 9.735311e+000 1.866837e+001 4.399139e+000 - vertex 9.427169e+000 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 -8.191520e-001 -6.296313e-016 - outer loop - vertex 9.070200e+000 1.922646e+001 -8.881784e-016 - vertex 9.427169e+000 1.897651e+001 4.399139e+000 - vertex 9.070200e+000 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 -9.063078e-001 -1.046600e-015 - outer loop - vertex 8.675250e+000 1.941063e+001 -8.881784e-016 - vertex 9.070200e+000 1.922646e+001 4.399139e+000 - vertex 8.675250e+000 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 -9.659258e-001 -1.310129e-015 - outer loop - vertex 8.254320e+000 1.952342e+001 -8.881784e-016 - vertex 8.675250e+000 1.941063e+001 4.399139e+000 - vertex 8.254320e+000 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 -9.961947e-001 -7.038636e-016 - outer loop - vertex 7.820200e+000 1.956140e+001 -8.881784e-016 - vertex 8.254320e+000 1.952342e+001 4.399139e+000 - vertex 7.820200e+000 1.956140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 -9.961947e-001 -9.051759e-016 - outer loop - vertex 7.386080e+000 1.952342e+001 -8.881784e-016 - vertex 7.820200e+000 1.956140e+001 4.399139e+000 - vertex 7.386080e+000 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 -9.659258e-001 -3.545305e-016 - outer loop - vertex 6.965150e+000 1.941063e+001 -8.881784e-016 - vertex 7.386080e+000 1.952342e+001 4.399139e+000 - vertex 6.965150e+000 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 -9.063078e-001 -7.585588e-016 - outer loop - vertex 6.570200e+000 1.922646e+001 -8.881784e-016 - vertex 6.965150e+000 1.941063e+001 4.399139e+000 - vertex 6.570200e+000 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 -8.191520e-001 -1.040864e-015 - outer loop - vertex 6.213231e+000 1.897651e+001 -8.881784e-016 - vertex 6.570200e+000 1.922646e+001 4.399139e+000 - vertex 6.213231e+000 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 -7.071068e-001 -8.565816e-016 - outer loop - vertex 5.905089e+000 1.866837e+001 -8.881784e-016 - vertex 6.213231e+000 1.897651e+001 4.399139e+000 - vertex 5.905089e+000 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 -5.735764e-001 -3.980232e-016 - outer loop - vertex 5.655136e+000 1.831140e+001 -8.881784e-016 - vertex 5.905089e+000 1.866837e+001 4.399139e+000 - vertex 5.655136e+000 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 -4.226183e-001 -8.512880e-016 - outer loop - vertex 5.470968e+000 1.791645e+001 -8.881784e-016 - vertex 5.655136e+000 1.831140e+001 4.399139e+000 - vertex 5.470968e+000 1.791645e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 -2.588190e-001 -7.250733e-016 - outer loop - vertex 5.358181e+000 1.749552e+001 -8.881784e-016 - vertex 5.470968e+000 1.791645e+001 4.399139e+000 - vertex 5.358181e+000 1.749552e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 -8.715574e-002 -7.038636e-016 - outer loop - vertex 5.320200e+000 1.706140e+001 -8.881784e-016 - vertex 5.358181e+000 1.749552e+001 4.399139e+000 - vertex 5.320200e+000 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 8.715574e-002 7.038636e-017 - outer loop - vertex 5.358181e+000 1.662728e+001 -8.881784e-016 - vertex 5.320200e+000 1.706140e+001 4.399139e+000 - vertex 5.358181e+000 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 2.588190e-001 -3.900374e-016 - outer loop - vertex 5.470968e+000 1.620635e+001 -8.881784e-016 - vertex 5.358181e+000 1.662728e+001 4.399139e+000 - vertex 5.470968e+000 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 4.226183e-001 -1.829819e-016 - outer loop - vertex 5.655136e+000 1.581140e+001 -8.881784e-016 - vertex 5.470968e+000 1.620635e+001 4.399139e+000 - vertex 5.655136e+000 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 5.735764e-001 6.622278e-017 - outer loop - vertex 5.905089e+000 1.545443e+001 -8.881784e-016 - vertex 5.655136e+000 1.581140e+001 4.399139e+000 - vertex 5.905089e+000 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal 7.071068e-001 7.071068e-001 -6.583952e-030 - outer loop - vertex 6.213231e+000 1.514629e+001 -8.881784e-016 - vertex 5.905089e+000 1.545443e+001 4.399139e+000 - vertex 6.213231e+000 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 8.191520e-001 2.149666e-016 - outer loop - vertex 6.570200e+000 1.489634e+001 -8.881784e-016 - vertex 6.213231e+000 1.514629e+001 4.399139e+000 - vertex 6.570200e+000 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 9.063078e-001 -2.559776e-016 - outer loop - vertex 6.965150e+000 1.471217e+001 -8.881784e-016 - vertex 6.570200e+000 1.489634e+001 4.399139e+000 - vertex 6.965150e+000 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 9.659258e-001 -1.567653e-016 - outer loop - vertex 7.386080e+000 1.459938e+001 -8.881784e-016 - vertex 6.965150e+000 1.471217e+001 4.399139e+000 - vertex 7.386080e+000 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 9.961947e-001 -1.759659e-017 - outer loop - vertex 7.820200e+000 1.456140e+001 -8.881784e-016 - vertex 7.386080e+000 1.459938e+001 4.399139e+000 - vertex 7.820200e+000 1.456140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 9.961947e-001 7.038636e-017 - outer loop - vertex 8.254320e+000 1.459938e+001 -8.881784e-016 - vertex 7.820200e+000 1.456140e+001 4.399139e+000 - vertex 8.254320e+000 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 9.659258e-001 -2.855272e-016 - outer loop - vertex 8.675250e+000 1.471217e+001 -8.881784e-016 - vertex 8.254320e+000 1.459938e+001 4.399139e+000 - vertex 8.675250e+000 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 9.063078e-001 -1.953121e-016 - outer loop - vertex 9.070200e+000 1.489634e+001 -8.881784e-016 - vertex 8.675250e+000 1.471217e+001 4.399139e+000 - vertex 9.070200e+000 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 8.191520e-001 -9.916256e-017 - outer loop - vertex 9.427169e+000 1.514629e+001 -8.881784e-016 - vertex 9.070200e+000 1.489634e+001 4.399139e+000 - vertex 9.427169e+000 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 7.071068e-001 0.000000e+000 - outer loop - vertex 9.735311e+000 1.545443e+001 -8.881784e-016 - vertex 9.427169e+000 1.514629e+001 4.399139e+000 - vertex 9.735311e+000 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 5.735764e-001 0.000000e+000 - outer loop - vertex 9.985264e+000 1.581140e+001 -8.881784e-016 - vertex 9.735311e+000 1.545443e+001 4.399139e+000 - vertex 9.985264e+000 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 4.226183e-001 3.659639e-016 - outer loop - vertex 1.016943e+001 1.620635e+001 -8.881784e-016 - vertex 9.985264e+000 1.581140e+001 4.399139e+000 - vertex 1.016943e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal -9.659258e-001 2.588190e-001 0.000000e+000 - outer loop - vertex 1.028222e+001 1.662728e+001 -8.881784e-016 - vertex 1.016943e+001 1.620635e+001 4.399139e+000 - vertex 1.028222e+001 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal -9.659258e-001 2.588190e-001 3.909131e-016 - outer loop - vertex 1.028222e+001 1.662728e+001 -8.881784e-016 - vertex 1.016943e+001 1.620635e+001 -8.881784e-016 - vertex 1.016943e+001 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 4.226183e-001 0.000000e+000 - outer loop - vertex 1.016943e+001 1.620635e+001 -8.881784e-016 - vertex 9.985264e+000 1.581140e+001 -8.881784e-016 - vertex 9.985264e+000 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 5.735764e-001 0.000000e+000 - outer loop - vertex 9.985264e+000 1.581140e+001 -8.881784e-016 - vertex 9.735311e+000 1.545443e+001 -8.881784e-016 - vertex 9.735311e+000 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 7.071068e-001 0.000000e+000 - outer loop - vertex 9.735311e+000 1.545443e+001 -8.881784e-016 - vertex 9.427169e+000 1.514629e+001 -8.881784e-016 - vertex 9.427169e+000 1.514629e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 8.191520e-001 -9.410872e-017 - outer loop - vertex 9.427169e+000 1.514629e+001 -8.881784e-016 - vertex 9.070200e+000 1.489634e+001 -8.881784e-016 - vertex 9.070200e+000 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 9.063078e-001 -1.954566e-016 - outer loop - vertex 9.070200e+000 1.489634e+001 -8.881784e-016 - vertex 8.675250e+000 1.471217e+001 -8.881784e-016 - vertex 8.675250e+000 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 9.659258e-001 2.099348e-016 - outer loop - vertex 8.675250e+000 1.471217e+001 -8.881784e-016 - vertex 8.254320e+000 1.459938e+001 -8.881784e-016 - vertex 8.254320e+000 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 9.961947e-001 1.809783e-017 - outer loop - vertex 8.254320e+000 1.459938e+001 -8.881784e-016 - vertex 7.820200e+000 1.456140e+001 -8.881784e-016 - vertex 7.820200e+000 1.456140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.715574e-002 9.961947e-001 -5.429349e-017 - outer loop - vertex 7.820200e+000 1.456140e+001 -8.881784e-016 - vertex 7.386080e+000 1.459938e+001 -8.881784e-016 - vertex 7.386080e+000 1.459938e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 9.659258e-001 -1.592609e-016 - outer loop - vertex 7.386080e+000 1.459938e+001 -8.881784e-016 - vertex 6.965150e+000 1.471217e+001 -8.881784e-016 - vertex 6.965150e+000 1.471217e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 9.063078e-001 2.750870e-016 - outer loop - vertex 6.965150e+000 1.471217e+001 -8.881784e-016 - vertex 6.570200e+000 1.489634e+001 -8.881784e-016 - vertex 6.570200e+000 1.489634e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 8.191520e-001 9.916256e-017 - outer loop - vertex 6.213231e+000 1.514629e+001 -8.881784e-016 - vertex 6.213231e+000 1.514629e+001 4.399139e+000 - vertex 6.570200e+000 1.489634e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.071068e-001 7.071068e-001 1.447826e-016 - outer loop - vertex 6.213231e+000 1.514629e+001 -8.881784e-016 - vertex 5.905089e+000 1.545443e+001 -8.881784e-016 - vertex 5.905089e+000 1.545443e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 5.735764e-001 -1.592609e-016 - outer loop - vertex 5.905089e+000 1.545443e+001 -8.881784e-016 - vertex 5.655136e+000 1.581140e+001 -8.881784e-016 - vertex 5.655136e+000 1.581140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.063078e-001 4.226183e-001 -3.691957e-016 - outer loop - vertex 5.655136e+000 1.581140e+001 -8.881784e-016 - vertex 5.470968e+000 1.620635e+001 -8.881784e-016 - vertex 5.470968e+000 1.620635e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 2.588190e-001 2.099348e-016 - outer loop - vertex 5.470968e+000 1.620635e+001 -8.881784e-016 - vertex 5.358181e+000 1.662728e+001 -8.881784e-016 - vertex 5.358181e+000 1.662728e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 8.715574e-002 7.040056e-016 - outer loop - vertex 5.358181e+000 1.662728e+001 -8.881784e-016 - vertex 5.320200e+000 1.706140e+001 -8.881784e-016 - vertex 5.320200e+000 1.706140e+001 4.399139e+000 - endloop - endfacet - facet normal 9.961947e-001 -8.715574e-002 7.040056e-016 - outer loop - vertex 5.320200e+000 1.706140e+001 -8.881784e-016 - vertex 5.358181e+000 1.749552e+001 -8.881784e-016 - vertex 5.358181e+000 1.749552e+001 4.399139e+000 - endloop - endfacet - facet normal 9.659258e-001 -2.588190e-001 6.400577e-016 - outer loop - vertex 5.470968e+000 1.791645e+001 -8.881784e-016 - vertex 5.470968e+000 1.791645e+001 4.399139e+000 - vertex 5.358181e+000 1.749552e+001 -8.881784e-016 - endloop - endfacet - facet normal 9.063078e-001 -4.226183e-001 9.338481e-016 - outer loop - vertex 5.470968e+000 1.791645e+001 -8.881784e-016 - vertex 5.655136e+000 1.831140e+001 -8.881784e-016 - vertex 5.655136e+000 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal 8.191520e-001 -5.735764e-001 5.942889e-016 - outer loop - vertex 5.905089e+000 1.866837e+001 -8.881784e-016 - vertex 5.905089e+000 1.866837e+001 4.399139e+000 - vertex 5.655136e+000 1.831140e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.071068e-001 -7.071068e-001 4.271088e-016 - outer loop - vertex 5.905089e+000 1.866837e+001 -8.881784e-016 - vertex 6.213231e+000 1.897651e+001 -8.881784e-016 - vertex 6.213231e+000 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal 5.735764e-001 -8.191520e-001 6.298045e-016 - outer loop - vertex 6.213231e+000 1.897651e+001 -8.881784e-016 - vertex 6.570200e+000 1.922646e+001 -8.881784e-016 - vertex 6.570200e+000 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal 4.226183e-001 -9.063078e-001 1.049674e-015 - outer loop - vertex 6.570200e+000 1.922646e+001 -8.881784e-016 - vertex 6.965150e+000 1.941063e+001 -8.881784e-016 - vertex 6.965150e+000 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal 2.588190e-001 -9.659258e-001 5.300545e-016 - outer loop - vertex 7.386080e+000 1.952342e+001 -8.881784e-016 - vertex 7.386080e+000 1.952342e+001 4.399139e+000 - vertex 6.965150e+000 1.941063e+001 -8.881784e-016 - endloop - endfacet - facet normal 8.715574e-002 -9.961947e-001 7.040056e-016 - outer loop - vertex 7.386080e+000 1.952342e+001 -8.881784e-016 - vertex 7.820200e+000 1.956140e+001 -8.881784e-016 - vertex 7.820200e+000 1.956140e+001 4.399139e+000 - endloop - endfacet - facet normal -8.715574e-002 -9.961947e-001 1.013479e-016 - outer loop - vertex 7.820200e+000 1.956140e+001 -8.881784e-016 - vertex 8.254320e+000 1.952342e+001 -8.881784e-016 - vertex 8.254320e+000 1.952342e+001 4.399139e+000 - endloop - endfacet - facet normal -2.588190e-001 -9.659258e-001 3.547175e-016 - outer loop - vertex 8.254320e+000 1.952342e+001 -8.881784e-016 - vertex 8.675250e+000 1.941063e+001 -8.881784e-016 - vertex 8.675250e+000 1.941063e+001 4.399139e+000 - endloop - endfacet - facet normal -4.226183e-001 -9.063078e-001 7.601089e-016 - outer loop - vertex 8.675250e+000 1.941063e+001 -8.881784e-016 - vertex 9.070200e+000 1.922646e+001 -8.881784e-016 - vertex 9.070200e+000 1.922646e+001 4.399139e+000 - endloop - endfacet - facet normal -5.735764e-001 -8.191520e-001 2.678479e-016 - outer loop - vertex 9.070200e+000 1.922646e+001 -8.881784e-016 - vertex 9.427169e+000 1.897651e+001 -8.881784e-016 - vertex 9.427169e+000 1.897651e+001 4.399139e+000 - endloop - endfacet - facet normal -7.071068e-001 -7.071068e-001 8.542176e-016 - outer loop - vertex 9.427169e+000 1.897651e+001 -8.881784e-016 - vertex 9.735311e+000 1.866837e+001 -8.881784e-016 - vertex 9.735311e+000 1.866837e+001 4.399139e+000 - endloop - endfacet - facet normal -8.191520e-001 -5.735764e-001 8.614567e-016 - outer loop - vertex 9.735311e+000 1.866837e+001 -8.881784e-016 - vertex 9.985264e+000 1.831140e+001 -8.881784e-016 - vertex 9.985264e+000 1.831140e+001 4.399139e+000 - endloop - endfacet - facet normal -9.063078e-001 -4.226183e-001 8.542176e-016 - outer loop - vertex 9.985264e+000 1.831140e+001 -8.881784e-016 - vertex 1.016943e+001 1.791645e+001 -8.881784e-016 - vertex 1.016943e+001 1.791645e+001 4.399139e+000 - endloop - endfacet - facet normal 4.639778e-016 9.961947e-001 -8.715574e-002 - outer loop - vertex -1.798000e-001 -2.938600e+000 5.000000e+000 - vertex -1.798000e-001 -2.893023e+000 5.520945e+000 - vertex 1.482020e+001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal -2.425509e-016 9.961947e-001 -8.715574e-002 - outer loop - vertex 1.482020e+001 -2.938600e+000 5.000000e+000 - vertex -1.798000e-001 -2.938600e+000 5.000000e+000 - vertex 1.482020e+001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal 2.425509e-016 9.961947e-001 8.715574e-002 - outer loop - vertex 1.482020e+001 -2.938600e+000 5.000000e+000 - vertex -1.798000e-001 -2.893023e+000 4.479055e+000 - vertex -1.798000e-001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -4.635355e-016 9.961947e-001 8.715574e-002 - outer loop - vertex 1.482020e+001 -2.938600e+000 5.000000e+000 - vertex 1.482020e+001 -2.893023e+000 4.479055e+000 - vertex -1.798000e-001 -2.893023e+000 4.479055e+000 - endloop - endfacet - facet normal 5.101317e-016 9.659258e-001 2.588190e-001 - outer loop - vertex -1.798000e-001 -2.893023e+000 4.479055e+000 - vertex 1.482020e+001 -2.893023e+000 4.479055e+000 - vertex -1.798000e-001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal -5.234721e-016 9.659258e-001 2.588190e-001 - outer loop - vertex -1.798000e-001 -2.757678e+000 3.973940e+000 - vertex 1.482020e+001 -2.893023e+000 4.479055e+000 - vertex 1.482020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal -4.809511e-016 9.063078e-001 4.226183e-001 - outer loop - vertex -1.798000e-001 -2.536676e+000 3.500000e+000 - vertex 1.482020e+001 -2.757678e+000 3.973940e+000 - vertex 1.482020e+001 -2.536676e+000 3.500000e+000 - endloop - endfacet - facet normal -5.134128e-016 8.191520e-001 5.735764e-001 - outer loop - vertex -1.798000e-001 -2.236733e+000 3.071637e+000 - vertex 1.482020e+001 -2.536676e+000 3.500000e+000 - vertex 1.482020e+001 -2.236733e+000 3.071637e+000 - endloop - endfacet - facet normal -5.024296e-016 7.071068e-001 7.071068e-001 - outer loop - vertex -1.798000e-001 -1.866963e+000 2.701867e+000 - vertex 1.482020e+001 -2.236733e+000 3.071637e+000 - vertex 1.482020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal -4.870609e-016 5.735764e-001 8.191520e-001 - outer loop - vertex -1.798000e-001 -1.438600e+000 2.401924e+000 - vertex 1.482020e+001 -1.866963e+000 2.701867e+000 - vertex 1.482020e+001 -1.438600e+000 2.401924e+000 - endloop - endfacet - facet normal -4.973720e-016 4.226183e-001 9.063078e-001 - outer loop - vertex -1.798000e-001 -9.646604e-001 2.180922e+000 - vertex 1.482020e+001 -1.438600e+000 2.401924e+000 - vertex 1.482020e+001 -9.646604e-001 2.180922e+000 - endloop - endfacet - facet normal -4.930284e-016 2.588190e-001 9.659258e-001 - outer loop - vertex -1.798000e-001 -4.595445e-001 2.045577e+000 - vertex 1.482020e+001 -9.646604e-001 2.180922e+000 - vertex 1.482020e+001 -4.595445e-001 2.045577e+000 - endloop - endfacet - facet normal -4.799411e-016 8.715574e-002 9.961947e-001 - outer loop - vertex -1.798000e-001 6.140000e-002 2.000000e+000 - vertex 1.482020e+001 -4.595445e-001 2.045577e+000 - vertex 1.482020e+001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal -4.933374e-016 -8.715574e-002 9.961947e-001 - outer loop - vertex -1.798000e-001 5.823445e-001 2.045577e+000 - vertex 1.482020e+001 6.140000e-002 2.000000e+000 - vertex 1.482020e+001 5.823445e-001 2.045577e+000 - endloop - endfacet - facet normal -4.872123e-016 -2.588190e-001 9.659258e-001 - outer loop - vertex -1.798000e-001 1.087460e+000 2.180922e+000 - vertex 1.482020e+001 5.823445e-001 2.045577e+000 - vertex 1.482020e+001 1.087460e+000 2.180922e+000 - endloop - endfacet - facet normal -4.809511e-016 -4.226183e-001 9.063078e-001 - outer loop - vertex -1.798000e-001 1.561400e+000 2.401924e+000 - vertex 1.482020e+001 1.087460e+000 2.180922e+000 - vertex 1.482020e+001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal -5.049222e-016 -5.735764e-001 8.191520e-001 - outer loop - vertex -1.798000e-001 1.989763e+000 2.701867e+000 - vertex 1.482020e+001 1.561400e+000 2.401924e+000 - vertex 1.482020e+001 1.989763e+000 2.701867e+000 - endloop - endfacet - facet normal -4.605605e-016 -7.071068e-001 7.071068e-001 - outer loop - vertex -1.798000e-001 2.359533e+000 3.071637e+000 - vertex 1.482020e+001 1.989763e+000 2.701867e+000 - vertex 1.482020e+001 2.359533e+000 3.071637e+000 - endloop - endfacet - facet normal -4.955515e-016 -8.191520e-001 5.735764e-001 - outer loop - vertex -1.798000e-001 2.659476e+000 3.500000e+000 - vertex 1.482020e+001 2.359533e+000 3.071637e+000 - vertex 1.482020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal -4.562199e-016 -9.063078e-001 4.226183e-001 - outer loop - vertex -1.798000e-001 2.880478e+000 3.973940e+000 - vertex 1.482020e+001 2.659476e+000 3.500000e+000 - vertex 1.482020e+001 2.880478e+000 3.973940e+000 - endloop - endfacet - facet normal -4.815345e-016 -9.659258e-001 2.588190e-001 - outer loop - vertex -1.798000e-001 3.015823e+000 4.479055e+000 - vertex 1.482020e+001 2.880478e+000 3.973940e+000 - vertex 1.482020e+001 3.015823e+000 4.479055e+000 - endloop - endfacet - facet normal -4.851017e-016 -9.961947e-001 8.715574e-002 - outer loop - vertex -1.798000e-001 3.061400e+000 5.000000e+000 - vertex 1.482020e+001 3.015823e+000 4.479055e+000 - vertex 1.482020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002 - outer loop - vertex -1.798000e-001 3.015823e+000 5.520945e+000 - vertex 1.482020e+001 3.061400e+000 5.000000e+000 - vertex 1.482020e+001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001 - outer loop - vertex -1.798000e-001 2.880478e+000 6.026060e+000 - vertex 1.482020e+001 3.015823e+000 5.520945e+000 - vertex 1.482020e+001 2.880478e+000 6.026060e+000 - endloop - endfacet - facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001 - outer loop - vertex -1.798000e-001 2.659476e+000 6.500000e+000 - vertex 1.482020e+001 2.880478e+000 6.026060e+000 - vertex 1.482020e+001 2.659476e+000 6.500000e+000 - endloop - endfacet - facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001 - outer loop - vertex -1.798000e-001 2.359533e+000 6.928363e+000 - vertex 1.482020e+001 2.659476e+000 6.500000e+000 - vertex 1.482020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001 - outer loop - vertex -1.798000e-001 1.989763e+000 7.298133e+000 - vertex 1.482020e+001 2.359533e+000 6.928363e+000 - vertex 1.482020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001 - outer loop - vertex -1.798000e-001 1.561400e+000 7.598076e+000 - vertex 1.482020e+001 1.989763e+000 7.298133e+000 - vertex 1.482020e+001 1.561400e+000 7.598076e+000 - endloop - endfacet - facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001 - outer loop - vertex -1.798000e-001 1.087460e+000 7.819078e+000 - vertex 1.482020e+001 1.561400e+000 7.598076e+000 - vertex 1.482020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001 - outer loop - vertex -1.798000e-001 5.823445e-001 7.954423e+000 - vertex 1.482020e+001 1.087460e+000 7.819078e+000 - vertex 1.482020e+001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001 - outer loop - vertex -1.798000e-001 6.140000e-002 8.000000e+000 - vertex 1.482020e+001 5.823445e-001 7.954423e+000 - vertex 1.482020e+001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal -5.189602e-016 8.715574e-002 -9.961947e-001 - outer loop - vertex -1.798000e-001 -4.595445e-001 7.954423e+000 - vertex 1.482020e+001 6.140000e-002 8.000000e+000 - vertex 1.482020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal -4.739404e-016 2.588190e-001 -9.659258e-001 - outer loop - vertex -1.798000e-001 -9.646604e-001 7.819078e+000 - vertex 1.482020e+001 -4.595445e-001 7.954423e+000 - vertex 1.482020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal -5.015272e-016 4.226183e-001 -9.063078e-001 - outer loop - vertex -1.798000e-001 -1.438600e+000 7.598076e+000 - vertex 1.482020e+001 -9.646604e-001 7.819078e+000 - vertex 1.482020e+001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal -4.479280e-016 5.735764e-001 -8.191520e-001 - outer loop - vertex -1.798000e-001 -1.866963e+000 7.298133e+000 - vertex 1.482020e+001 -1.438600e+000 7.598076e+000 - vertex 1.482020e+001 -1.866963e+000 7.298133e+000 - endloop - endfacet - facet normal -4.605605e-016 7.071068e-001 -7.071068e-001 - outer loop - vertex -1.798000e-001 -2.236733e+000 6.928363e+000 - vertex 1.482020e+001 -1.866963e+000 7.298133e+000 - vertex 1.482020e+001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal -4.955515e-016 8.191520e-001 -5.735764e-001 - outer loop - vertex -1.798000e-001 -2.536676e+000 6.500000e+000 - vertex 1.482020e+001 -2.236733e+000 6.928363e+000 - vertex 1.482020e+001 -2.536676e+000 6.500000e+000 - endloop - endfacet - facet normal -4.562199e-016 9.063078e-001 -4.226183e-001 - outer loop - vertex -1.798000e-001 -2.757678e+000 6.026060e+000 - vertex 1.482020e+001 -2.536676e+000 6.500000e+000 - vertex 1.482020e+001 -2.757678e+000 6.026060e+000 - endloop - endfacet - facet normal -5.101317e-016 9.659258e-001 -2.588190e-001 - outer loop - vertex -1.798000e-001 -2.893023e+000 5.520945e+000 - vertex 1.482020e+001 -2.757678e+000 6.026060e+000 - vertex 1.482020e+001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal 5.236890e-016 9.659258e-001 -2.588190e-001 - outer loop - vertex -1.798000e-001 -2.893023e+000 5.520945e+000 - vertex -1.798000e-001 -2.757678e+000 6.026060e+000 - vertex 1.482020e+001 -2.757678e+000 6.026060e+000 - endloop - endfacet - facet normal 4.688432e-016 9.063078e-001 -4.226183e-001 - outer loop - vertex -1.798000e-001 -2.757678e+000 6.026060e+000 - vertex -1.798000e-001 -2.536676e+000 6.500000e+000 - vertex 1.482020e+001 -2.536676e+000 6.500000e+000 - endloop - endfacet - facet normal 5.130737e-016 8.191520e-001 -5.735764e-001 - outer loop - vertex -1.798000e-001 -2.536676e+000 6.500000e+000 - vertex -1.798000e-001 -2.236733e+000 6.928363e+000 - vertex 1.482020e+001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal 5.236890e-016 7.071068e-001 -7.071068e-001 - outer loop - vertex -1.798000e-001 -2.236733e+000 6.928363e+000 - vertex -1.798000e-001 -1.866963e+000 7.298133e+000 - vertex 1.482020e+001 -1.866963e+000 7.298133e+000 - endloop - endfacet - facet normal 4.635355e-016 5.735764e-001 -8.191520e-001 - outer loop - vertex -1.798000e-001 -1.866963e+000 7.298133e+000 - vertex -1.798000e-001 -1.438600e+000 7.598076e+000 - vertex 1.482020e+001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal 4.971507e-016 4.226183e-001 -9.063078e-001 - outer loop - vertex -1.798000e-001 -1.438600e+000 7.598076e+000 - vertex -1.798000e-001 -9.646604e-001 7.819078e+000 - vertex 1.482020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal 4.635355e-016 2.588190e-001 -9.659258e-001 - outer loop - vertex -1.798000e-001 -9.646604e-001 7.819078e+000 - vertex -1.798000e-001 -4.595445e-001 7.954423e+000 - vertex 1.482020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal 4.799008e-016 8.715574e-002 -9.961947e-001 - outer loop - vertex -1.798000e-001 -4.595445e-001 7.954423e+000 - vertex -1.798000e-001 6.140000e-002 8.000000e+000 - vertex 1.482020e+001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001 - outer loop - vertex -1.798000e-001 6.140000e-002 8.000000e+000 - vertex -1.798000e-001 5.823445e-001 7.954423e+000 - vertex 1.482020e+001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001 - outer loop - vertex -1.798000e-001 5.823445e-001 7.954423e+000 - vertex -1.798000e-001 1.087460e+000 7.819078e+000 - vertex 1.482020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001 - outer loop - vertex -1.798000e-001 1.087460e+000 7.819078e+000 - vertex -1.798000e-001 1.561400e+000 7.598076e+000 - vertex 1.482020e+001 1.561400e+000 7.598076e+000 - endloop - endfacet - facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001 - outer loop - vertex -1.798000e-001 1.561400e+000 7.598076e+000 - vertex -1.798000e-001 1.989763e+000 7.298133e+000 - vertex 1.482020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001 - outer loop - vertex -1.798000e-001 1.989763e+000 7.298133e+000 - vertex -1.798000e-001 2.359533e+000 6.928363e+000 - vertex 1.482020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001 - outer loop - vertex -1.798000e-001 2.359533e+000 6.928363e+000 - vertex -1.798000e-001 2.659476e+000 6.500000e+000 - vertex 1.482020e+001 2.659476e+000 6.500000e+000 - endloop - endfacet - facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001 - outer loop - vertex -1.798000e-001 2.659476e+000 6.500000e+000 - vertex -1.798000e-001 2.880478e+000 6.026060e+000 - vertex 1.482020e+001 2.880478e+000 6.026060e+000 - endloop - endfacet - facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001 - outer loop - vertex -1.798000e-001 2.880478e+000 6.026060e+000 - vertex -1.798000e-001 3.015823e+000 5.520945e+000 - vertex 1.482020e+001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002 - outer loop - vertex -1.798000e-001 3.015823e+000 5.520945e+000 - vertex -1.798000e-001 3.061400e+000 5.000000e+000 - vertex 1.482020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 4.936122e-016 -9.961947e-001 8.715574e-002 - outer loop - vertex -1.798000e-001 3.061400e+000 5.000000e+000 - vertex -1.798000e-001 3.015823e+000 4.479055e+000 - vertex 1.482020e+001 3.015823e+000 4.479055e+000 - endloop - endfacet - facet normal 5.236890e-016 -9.659258e-001 2.588190e-001 - outer loop - vertex -1.798000e-001 3.015823e+000 4.479055e+000 - vertex -1.798000e-001 2.880478e+000 3.973940e+000 - vertex 1.482020e+001 2.880478e+000 3.973940e+000 - endloop - endfacet - facet normal 4.670740e-016 -9.063078e-001 4.226183e-001 - outer loop - vertex -1.798000e-001 2.880478e+000 3.973940e+000 - vertex -1.798000e-001 2.659476e+000 3.500000e+000 - vertex 1.482020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal 5.130737e-016 -8.191520e-001 5.735764e-001 - outer loop - vertex -1.798000e-001 2.659476e+000 3.500000e+000 - vertex -1.798000e-001 2.359533e+000 3.071637e+000 - vertex 1.482020e+001 2.359533e+000 3.071637e+000 - endloop - endfacet - facet normal 4.706124e-016 -7.071068e-001 7.071068e-001 - outer loop - vertex -1.798000e-001 2.359533e+000 3.071637e+000 - vertex -1.798000e-001 1.989763e+000 2.701867e+000 - vertex 1.482020e+001 1.989763e+000 2.701867e+000 - endloop - endfacet - facet normal 4.776893e-016 -5.735764e-001 8.191520e-001 - outer loop - vertex -1.798000e-001 1.989763e+000 2.701867e+000 - vertex -1.798000e-001 1.561400e+000 2.401924e+000 - vertex 1.482020e+001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal 4.953815e-016 -4.226183e-001 9.063078e-001 - outer loop - vertex -1.798000e-001 1.561400e+000 2.401924e+000 - vertex -1.798000e-001 1.087460e+000 2.180922e+000 - vertex 1.482020e+001 1.087460e+000 2.180922e+000 - endloop - endfacet - facet normal 4.812277e-016 -2.588190e-001 9.659258e-001 - outer loop - vertex -1.798000e-001 1.087460e+000 2.180922e+000 - vertex -1.798000e-001 5.823445e-001 2.045577e+000 - vertex 1.482020e+001 5.823445e-001 2.045577e+000 - endloop - endfacet - facet normal 4.799008e-016 -8.715574e-002 9.961947e-001 - outer loop - vertex -1.798000e-001 5.823445e-001 2.045577e+000 - vertex -1.798000e-001 6.140000e-002 2.000000e+000 - vertex 1.482020e+001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal 4.891892e-016 8.715574e-002 9.961947e-001 - outer loop - vertex -1.798000e-001 6.140000e-002 2.000000e+000 - vertex -1.798000e-001 -4.595445e-001 2.045577e+000 - vertex 1.482020e+001 -4.595445e-001 2.045577e+000 - endloop - endfacet - facet normal 4.741508e-016 2.588190e-001 9.659258e-001 - outer loop - vertex -1.798000e-001 -4.595445e-001 2.045577e+000 - vertex -1.798000e-001 -9.646604e-001 2.180922e+000 - vertex 1.482020e+001 -9.646604e-001 2.180922e+000 - endloop - endfacet - facet normal 4.759201e-016 4.226183e-001 9.063078e-001 - outer loop - vertex -1.798000e-001 -9.646604e-001 2.180922e+000 - vertex -1.798000e-001 -1.438600e+000 2.401924e+000 - vertex 1.482020e+001 -1.438600e+000 2.401924e+000 - endloop - endfacet - facet normal 4.706124e-016 5.735764e-001 8.191520e-001 - outer loop - vertex -1.798000e-001 -1.438600e+000 2.401924e+000 - vertex -1.798000e-001 -1.866963e+000 2.701867e+000 - vertex 1.482020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal 4.599971e-016 7.071068e-001 7.071068e-001 - outer loop - vertex -1.798000e-001 -1.866963e+000 2.701867e+000 - vertex -1.798000e-001 -2.236733e+000 3.071637e+000 - vertex 1.482020e+001 -2.236733e+000 3.071637e+000 - endloop - endfacet - facet normal 4.812277e-016 8.191520e-001 5.735764e-001 - outer loop - vertex -1.798000e-001 -2.236733e+000 3.071637e+000 - vertex -1.798000e-001 -2.536676e+000 3.500000e+000 - vertex 1.482020e+001 -2.536676e+000 3.500000e+000 - endloop - endfacet - facet normal 4.546894e-016 9.063078e-001 4.226183e-001 - outer loop - vertex -1.798000e-001 -2.536676e+000 3.500000e+000 - vertex -1.798000e-001 -2.757678e+000 3.973940e+000 - vertex 1.482020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal 4.639778e-016 9.961947e-001 -8.715574e-002 - outer loop - vertex 3.482020e+001 -2.938600e+000 5.000000e+000 - vertex 3.482020e+001 -2.893023e+000 5.520945e+000 - vertex 4.982020e+001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal -2.425509e-016 9.961947e-001 -8.715574e-002 - outer loop - vertex 4.982020e+001 -2.938600e+000 5.000000e+000 - vertex 3.482020e+001 -2.938600e+000 5.000000e+000 - vertex 4.982020e+001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal 2.425509e-016 9.961947e-001 8.715574e-002 - outer loop - vertex 4.982020e+001 -2.938600e+000 5.000000e+000 - vertex 3.482020e+001 -2.893023e+000 4.479055e+000 - vertex 3.482020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -4.635355e-016 9.961947e-001 8.715574e-002 - outer loop - vertex 4.982020e+001 -2.938600e+000 5.000000e+000 - vertex 4.982020e+001 -2.893023e+000 4.479055e+000 - vertex 3.482020e+001 -2.893023e+000 4.479055e+000 - endloop - endfacet - facet normal 5.101317e-016 9.659258e-001 2.588190e-001 - outer loop - vertex 3.482020e+001 -2.893023e+000 4.479055e+000 - vertex 4.982020e+001 -2.893023e+000 4.479055e+000 - vertex 3.482020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal -5.234721e-016 9.659258e-001 2.588190e-001 - outer loop - vertex 3.482020e+001 -2.757678e+000 3.973940e+000 - vertex 4.982020e+001 -2.893023e+000 4.479055e+000 - vertex 4.982020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal -4.809511e-016 9.063078e-001 4.226183e-001 - outer loop - vertex 3.482020e+001 -2.536676e+000 3.500000e+000 - vertex 4.982020e+001 -2.757678e+000 3.973940e+000 - vertex 4.982020e+001 -2.536676e+000 3.500000e+000 - endloop - endfacet - facet normal -5.134128e-016 8.191520e-001 5.735764e-001 - outer loop - vertex 3.482020e+001 -2.236733e+000 3.071637e+000 - vertex 4.982020e+001 -2.536676e+000 3.500000e+000 - vertex 4.982020e+001 -2.236733e+000 3.071637e+000 - endloop - endfacet - facet normal -5.024296e-016 7.071068e-001 7.071068e-001 - outer loop - vertex 3.482020e+001 -1.866963e+000 2.701867e+000 - vertex 4.982020e+001 -2.236733e+000 3.071637e+000 - vertex 4.982020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal -4.870609e-016 5.735764e-001 8.191520e-001 - outer loop - vertex 3.482020e+001 -1.438600e+000 2.401924e+000 - vertex 4.982020e+001 -1.866963e+000 2.701867e+000 - vertex 4.982020e+001 -1.438600e+000 2.401924e+000 - endloop - endfacet - facet normal -4.973720e-016 4.226183e-001 9.063078e-001 - outer loop - vertex 3.482020e+001 -9.646604e-001 2.180922e+000 - vertex 4.982020e+001 -1.438600e+000 2.401924e+000 - vertex 4.982020e+001 -9.646604e-001 2.180922e+000 - endloop - endfacet - facet normal -4.930284e-016 2.588190e-001 9.659258e-001 - outer loop - vertex 3.482020e+001 -4.595445e-001 2.045577e+000 - vertex 4.982020e+001 -9.646604e-001 2.180922e+000 - vertex 4.982020e+001 -4.595445e-001 2.045577e+000 - endloop - endfacet - facet normal -4.799411e-016 8.715574e-002 9.961947e-001 - outer loop - vertex 3.482020e+001 6.140000e-002 2.000000e+000 - vertex 4.982020e+001 -4.595445e-001 2.045577e+000 - vertex 4.982020e+001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal -4.933374e-016 -8.715574e-002 9.961947e-001 - outer loop - vertex 3.482020e+001 5.823445e-001 2.045577e+000 - vertex 4.982020e+001 6.140000e-002 2.000000e+000 - vertex 4.982020e+001 5.823445e-001 2.045577e+000 - endloop - endfacet - facet normal -4.872123e-016 -2.588190e-001 9.659258e-001 - outer loop - vertex 3.482020e+001 1.087460e+000 2.180922e+000 - vertex 4.982020e+001 5.823445e-001 2.045577e+000 - vertex 4.982020e+001 1.087460e+000 2.180922e+000 - endloop - endfacet - facet normal -4.809511e-016 -4.226183e-001 9.063078e-001 - outer loop - vertex 3.482020e+001 1.561400e+000 2.401924e+000 - vertex 4.982020e+001 1.087460e+000 2.180922e+000 - vertex 4.982020e+001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal -5.049222e-016 -5.735764e-001 8.191520e-001 - outer loop - vertex 3.482020e+001 1.989763e+000 2.701867e+000 - vertex 4.982020e+001 1.561400e+000 2.401924e+000 - vertex 4.982020e+001 1.989763e+000 2.701867e+000 - endloop - endfacet - facet normal -4.605605e-016 -7.071068e-001 7.071068e-001 - outer loop - vertex 3.482020e+001 2.359533e+000 3.071637e+000 - vertex 4.982020e+001 1.989763e+000 2.701867e+000 - vertex 4.982020e+001 2.359533e+000 3.071637e+000 - endloop - endfacet - facet normal -4.955515e-016 -8.191520e-001 5.735764e-001 - outer loop - vertex 3.482020e+001 2.659476e+000 3.500000e+000 - vertex 4.982020e+001 2.359533e+000 3.071637e+000 - vertex 4.982020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal -4.562199e-016 -9.063078e-001 4.226183e-001 - outer loop - vertex 3.482020e+001 2.880478e+000 3.973940e+000 - vertex 4.982020e+001 2.659476e+000 3.500000e+000 - vertex 4.982020e+001 2.880478e+000 3.973940e+000 - endloop - endfacet - facet normal -4.815345e-016 -9.659258e-001 2.588190e-001 - outer loop - vertex 3.482020e+001 3.015823e+000 4.479055e+000 - vertex 4.982020e+001 2.880478e+000 3.973940e+000 - vertex 4.982020e+001 3.015823e+000 4.479055e+000 - endloop - endfacet - facet normal -4.851017e-016 -9.961947e-001 8.715574e-002 - outer loop - vertex 3.482020e+001 3.061400e+000 5.000000e+000 - vertex 4.982020e+001 3.015823e+000 4.479055e+000 - vertex 4.982020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -4.933374e-016 -9.961947e-001 -8.715574e-002 - outer loop - vertex 3.482020e+001 3.015823e+000 5.520945e+000 - vertex 4.982020e+001 3.061400e+000 5.000000e+000 - vertex 4.982020e+001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal -5.234721e-016 -9.659258e-001 -2.588190e-001 - outer loop - vertex 3.482020e+001 2.880478e+000 6.026060e+000 - vertex 4.982020e+001 3.015823e+000 5.520945e+000 - vertex 4.982020e+001 2.880478e+000 6.026060e+000 - endloop - endfacet - facet normal -4.684391e-016 -9.063078e-001 -4.226183e-001 - outer loop - vertex 3.482020e+001 2.659476e+000 6.500000e+000 - vertex 4.982020e+001 2.880478e+000 6.026060e+000 - vertex 4.982020e+001 2.659476e+000 6.500000e+000 - endloop - endfacet - facet normal -5.134128e-016 -8.191520e-001 -5.735764e-001 - outer loop - vertex 3.482020e+001 2.359533e+000 6.928363e+000 - vertex 4.982020e+001 2.659476e+000 6.500000e+000 - vertex 4.982020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal -5.128969e-016 -7.071068e-001 -7.071068e-001 - outer loop - vertex 3.482020e+001 1.989763e+000 7.298133e+000 - vertex 4.982020e+001 2.359533e+000 6.928363e+000 - vertex 4.982020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal -4.543185e-016 -5.735764e-001 -8.191520e-001 - outer loop - vertex 3.482020e+001 1.561400e+000 7.598076e+000 - vertex 4.982020e+001 1.989763e+000 7.298133e+000 - vertex 4.982020e+001 1.561400e+000 7.598076e+000 - endloop - endfacet - facet normal -5.223961e-016 -4.226183e-001 -9.063078e-001 - outer loop - vertex 3.482020e+001 1.087460e+000 7.819078e+000 - vertex 4.982020e+001 1.561400e+000 7.598076e+000 - vertex 4.982020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal -4.529374e-016 -2.588190e-001 -9.659258e-001 - outer loop - vertex 3.482020e+001 5.823445e-001 7.954423e+000 - vertex 4.982020e+001 1.087460e+000 7.819078e+000 - vertex 4.982020e+001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal -4.799411e-016 -8.715574e-002 -9.961947e-001 - outer loop - vertex 3.482020e+001 6.140000e-002 8.000000e+000 - vertex 4.982020e+001 5.823445e-001 7.954423e+000 - vertex 4.982020e+001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal -5.189602e-016 8.715574e-002 -9.961947e-001 - outer loop - vertex 3.482020e+001 -4.595445e-001 7.954423e+000 - vertex 4.982020e+001 6.140000e-002 8.000000e+000 - vertex 4.982020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal -4.739404e-016 2.588190e-001 -9.659258e-001 - outer loop - vertex 3.482020e+001 -9.646604e-001 7.819078e+000 - vertex 4.982020e+001 -4.595445e-001 7.954423e+000 - vertex 4.982020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal -5.015272e-016 4.226183e-001 -9.063078e-001 - outer loop - vertex 3.482020e+001 -1.438600e+000 7.598076e+000 - vertex 4.982020e+001 -9.646604e-001 7.819078e+000 - vertex 4.982020e+001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal -4.479280e-016 5.735764e-001 -8.191520e-001 - outer loop - vertex 3.482020e+001 -1.866963e+000 7.298133e+000 - vertex 4.982020e+001 -1.438600e+000 7.598076e+000 - vertex 4.982020e+001 -1.866963e+000 7.298133e+000 - endloop - endfacet - facet normal -4.605605e-016 7.071068e-001 -7.071068e-001 - outer loop - vertex 3.482020e+001 -2.236733e+000 6.928363e+000 - vertex 4.982020e+001 -1.866963e+000 7.298133e+000 - vertex 4.982020e+001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal -4.955515e-016 8.191520e-001 -5.735764e-001 - outer loop - vertex 3.482020e+001 -2.536676e+000 6.500000e+000 - vertex 4.982020e+001 -2.236733e+000 6.928363e+000 - vertex 4.982020e+001 -2.536676e+000 6.500000e+000 - endloop - endfacet - facet normal -4.562199e-016 9.063078e-001 -4.226183e-001 - outer loop - vertex 3.482020e+001 -2.757678e+000 6.026060e+000 - vertex 4.982020e+001 -2.536676e+000 6.500000e+000 - vertex 4.982020e+001 -2.757678e+000 6.026060e+000 - endloop - endfacet - facet normal -5.101317e-016 9.659258e-001 -2.588190e-001 - outer loop - vertex 3.482020e+001 -2.893023e+000 5.520945e+000 - vertex 4.982020e+001 -2.757678e+000 6.026060e+000 - vertex 4.982020e+001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal 5.236890e-016 9.659258e-001 -2.588190e-001 - outer loop - vertex 3.482020e+001 -2.893023e+000 5.520945e+000 - vertex 3.482020e+001 -2.757678e+000 6.026060e+000 - vertex 4.982020e+001 -2.757678e+000 6.026060e+000 - endloop - endfacet - facet normal 4.688432e-016 9.063078e-001 -4.226183e-001 - outer loop - vertex 3.482020e+001 -2.757678e+000 6.026060e+000 - vertex 3.482020e+001 -2.536676e+000 6.500000e+000 - vertex 4.982020e+001 -2.536676e+000 6.500000e+000 - endloop - endfacet - facet normal 5.130737e-016 8.191520e-001 -5.735764e-001 - outer loop - vertex 3.482020e+001 -2.536676e+000 6.500000e+000 - vertex 3.482020e+001 -2.236733e+000 6.928363e+000 - vertex 4.982020e+001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal 5.236890e-016 7.071068e-001 -7.071068e-001 - outer loop - vertex 3.482020e+001 -2.236733e+000 6.928363e+000 - vertex 3.482020e+001 -1.866963e+000 7.298133e+000 - vertex 4.982020e+001 -1.866963e+000 7.298133e+000 - endloop - endfacet - facet normal 4.635355e-016 5.735764e-001 -8.191520e-001 - outer loop - vertex 3.482020e+001 -1.866963e+000 7.298133e+000 - vertex 3.482020e+001 -1.438600e+000 7.598076e+000 - vertex 4.982020e+001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal 4.971507e-016 4.226183e-001 -9.063078e-001 - outer loop - vertex 3.482020e+001 -1.438600e+000 7.598076e+000 - vertex 3.482020e+001 -9.646604e-001 7.819078e+000 - vertex 4.982020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal 4.635355e-016 2.588190e-001 -9.659258e-001 - outer loop - vertex 3.482020e+001 -9.646604e-001 7.819078e+000 - vertex 3.482020e+001 -4.595445e-001 7.954423e+000 - vertex 4.982020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal 4.799008e-016 8.715574e-002 -9.961947e-001 - outer loop - vertex 3.482020e+001 -4.595445e-001 7.954423e+000 - vertex 3.482020e+001 6.140000e-002 8.000000e+000 - vertex 4.982020e+001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal 5.228044e-016 -8.715574e-002 -9.961947e-001 - outer loop - vertex 3.482020e+001 6.140000e-002 8.000000e+000 - vertex 3.482020e+001 5.823445e-001 7.954423e+000 - vertex 4.982020e+001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal 4.582279e-016 -2.588190e-001 -9.659258e-001 - outer loop - vertex 3.482020e+001 5.823445e-001 7.954423e+000 - vertex 3.482020e+001 1.087460e+000 7.819078e+000 - vertex 4.982020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal 5.077660e-016 -4.226183e-001 -9.063078e-001 - outer loop - vertex 3.482020e+001 1.087460e+000 7.819078e+000 - vertex 3.482020e+001 1.561400e+000 7.598076e+000 - vertex 4.982020e+001 1.561400e+000 7.598076e+000 - endloop - endfacet - facet normal 4.564586e-016 -5.735764e-001 -8.191520e-001 - outer loop - vertex 3.482020e+001 1.561400e+000 7.598076e+000 - vertex 3.482020e+001 1.989763e+000 7.298133e+000 - vertex 4.982020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal 4.599971e-016 -7.071068e-001 -7.071068e-001 - outer loop - vertex 3.482020e+001 1.989763e+000 7.298133e+000 - vertex 3.482020e+001 2.359533e+000 6.928363e+000 - vertex 4.982020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal 4.953815e-016 -8.191520e-001 -5.735764e-001 - outer loop - vertex 3.482020e+001 2.359533e+000 6.928363e+000 - vertex 3.482020e+001 2.659476e+000 6.500000e+000 - vertex 4.982020e+001 2.659476e+000 6.500000e+000 - endloop - endfacet - facet normal 4.564586e-016 -9.063078e-001 -4.226183e-001 - outer loop - vertex 3.482020e+001 2.659476e+000 6.500000e+000 - vertex 3.482020e+001 2.880478e+000 6.026060e+000 - vertex 4.982020e+001 2.880478e+000 6.026060e+000 - endloop - endfacet - facet normal 4.829969e-016 -9.659258e-001 -2.588190e-001 - outer loop - vertex 3.482020e+001 2.880478e+000 6.026060e+000 - vertex 3.482020e+001 3.015823e+000 5.520945e+000 - vertex 4.982020e+001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal 4.852085e-016 -9.961947e-001 -8.715574e-002 - outer loop - vertex 3.482020e+001 3.015823e+000 5.520945e+000 - vertex 3.482020e+001 3.061400e+000 5.000000e+000 - vertex 4.982020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 4.936122e-016 -9.961947e-001 8.715574e-002 - outer loop - vertex 3.482020e+001 3.061400e+000 5.000000e+000 - vertex 3.482020e+001 3.015823e+000 4.479055e+000 - vertex 4.982020e+001 3.015823e+000 4.479055e+000 - endloop - endfacet - facet normal 5.236890e-016 -9.659258e-001 2.588190e-001 - outer loop - vertex 3.482020e+001 3.015823e+000 4.479055e+000 - vertex 3.482020e+001 2.880478e+000 3.973940e+000 - vertex 4.982020e+001 2.880478e+000 3.973940e+000 - endloop - endfacet - facet normal 4.670740e-016 -9.063078e-001 4.226183e-001 - outer loop - vertex 3.482020e+001 2.880478e+000 3.973940e+000 - vertex 3.482020e+001 2.659476e+000 3.500000e+000 - vertex 4.982020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal 5.130737e-016 -8.191520e-001 5.735764e-001 - outer loop - vertex 3.482020e+001 2.659476e+000 3.500000e+000 - vertex 3.482020e+001 2.359533e+000 3.071637e+000 - vertex 4.982020e+001 2.359533e+000 3.071637e+000 - endloop - endfacet - facet normal 4.706124e-016 -7.071068e-001 7.071068e-001 - outer loop - vertex 3.482020e+001 2.359533e+000 3.071637e+000 - vertex 3.482020e+001 1.989763e+000 2.701867e+000 - vertex 4.982020e+001 1.989763e+000 2.701867e+000 - endloop - endfacet - facet normal 4.776893e-016 -5.735764e-001 8.191520e-001 - outer loop - vertex 3.482020e+001 1.989763e+000 2.701867e+000 - vertex 3.482020e+001 1.561400e+000 2.401924e+000 - vertex 4.982020e+001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal 4.953815e-016 -4.226183e-001 9.063078e-001 - outer loop - vertex 3.482020e+001 1.561400e+000 2.401924e+000 - vertex 3.482020e+001 1.087460e+000 2.180922e+000 - vertex 4.982020e+001 1.087460e+000 2.180922e+000 - endloop - endfacet - facet normal 4.812277e-016 -2.588190e-001 9.659258e-001 - outer loop - vertex 3.482020e+001 1.087460e+000 2.180922e+000 - vertex 3.482020e+001 5.823445e-001 2.045577e+000 - vertex 4.982020e+001 5.823445e-001 2.045577e+000 - endloop - endfacet - facet normal 4.799008e-016 -8.715574e-002 9.961947e-001 - outer loop - vertex 3.482020e+001 5.823445e-001 2.045577e+000 - vertex 3.482020e+001 6.140000e-002 2.000000e+000 - vertex 4.982020e+001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal 4.891892e-016 8.715574e-002 9.961947e-001 - outer loop - vertex 3.482020e+001 6.140000e-002 2.000000e+000 - vertex 3.482020e+001 -4.595445e-001 2.045577e+000 - vertex 4.982020e+001 -4.595445e-001 2.045577e+000 - endloop - endfacet - facet normal 4.741508e-016 2.588190e-001 9.659258e-001 - outer loop - vertex 3.482020e+001 -4.595445e-001 2.045577e+000 - vertex 3.482020e+001 -9.646604e-001 2.180922e+000 - vertex 4.982020e+001 -9.646604e-001 2.180922e+000 - endloop - endfacet - facet normal 4.759201e-016 4.226183e-001 9.063078e-001 - outer loop - vertex 3.482020e+001 -9.646604e-001 2.180922e+000 - vertex 3.482020e+001 -1.438600e+000 2.401924e+000 - vertex 4.982020e+001 -1.438600e+000 2.401924e+000 - endloop - endfacet - facet normal 4.706124e-016 5.735764e-001 8.191520e-001 - outer loop - vertex 3.482020e+001 -1.438600e+000 2.401924e+000 - vertex 3.482020e+001 -1.866963e+000 2.701867e+000 - vertex 4.982020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal 4.599971e-016 7.071068e-001 7.071068e-001 - outer loop - vertex 3.482020e+001 -1.866963e+000 2.701867e+000 - vertex 3.482020e+001 -2.236733e+000 3.071637e+000 - vertex 4.982020e+001 -2.236733e+000 3.071637e+000 - endloop - endfacet - facet normal 4.812277e-016 8.191520e-001 5.735764e-001 - outer loop - vertex 3.482020e+001 -2.236733e+000 3.071637e+000 - vertex 3.482020e+001 -2.536676e+000 3.500000e+000 - vertex 4.982020e+001 -2.536676e+000 3.500000e+000 - endloop - endfacet - facet normal 4.546894e-016 9.063078e-001 4.226183e-001 - outer loop - vertex 3.482020e+001 -2.536676e+000 3.500000e+000 - vertex 3.482020e+001 -2.757678e+000 3.973940e+000 - vertex 4.982020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.893023e+000 4.479055e+000 - vertex 3.482020e+001 -4.938600e+000 5.000000e+000 - vertex 3.482020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.893023e+000 4.479055e+000 - vertex 3.482020e+001 -4.862639e+000 4.131759e+000 - vertex 3.482020e+001 -4.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.893023e+000 4.479055e+000 - vertex 3.482020e+001 -2.757678e+000 3.973940e+000 - vertex 3.482020e+001 -4.862639e+000 4.131759e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.862639e+000 4.131759e+000 - vertex 3.482020e+001 -2.757678e+000 3.973940e+000 - vertex 3.482020e+001 -4.637063e+000 3.289899e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.637063e+000 3.289899e+000 - vertex 3.482020e+001 -2.757678e+000 3.973940e+000 - vertex 3.482020e+001 -2.536676e+000 3.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.268727e+000 2.500000e+000 - vertex 3.482020e+001 -2.536676e+000 3.500000e+000 - vertex 3.482020e+001 -2.236733e+000 3.071637e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -3.768822e+000 1.786062e+000 - vertex 3.482020e+001 -2.236733e+000 3.071637e+000 - vertex 3.482020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -3.152538e+000 1.169778e+000 - vertex 3.482020e+001 -1.866963e+000 2.701867e+000 - vertex 3.482020e+001 -2.438600e+000 6.698730e-001 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -3.152538e+000 1.169778e+000 - vertex 3.482020e+001 -3.768822e+000 1.786062e+000 - vertex 3.482020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -1.866963e+000 2.701867e+000 - vertex 3.482020e+001 -1.438600e+000 2.401924e+000 - vertex 3.482020e+001 -2.438600e+000 6.698730e-001 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.438600e+000 6.698730e-001 - vertex 3.482020e+001 -1.438600e+000 2.401924e+000 - vertex 3.482020e+001 -1.648701e+000 3.015369e-001 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -1.648701e+000 3.015369e-001 - vertex 3.482020e+001 -1.438600e+000 2.401924e+000 - vertex 3.482020e+001 -9.646604e-001 2.180922e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -8.068409e-001 7.596123e-002 - vertex 3.482020e+001 -9.646604e-001 2.180922e+000 - vertex 3.482020e+001 -4.595445e-001 2.045577e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 6.140000e-002 0.000000e+000 - vertex 3.482020e+001 -4.595445e-001 2.045577e+000 - vertex 3.482020e+001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.823445e-001 2.045577e+000 - vertex 3.482020e+001 6.140000e-002 0.000000e+000 - vertex 3.482020e+001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.823445e-001 2.045577e+000 - vertex 3.482020e+001 1.087460e+000 2.180922e+000 - vertex 3.482020e+001 6.140000e-002 0.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 6.140000e-002 0.000000e+000 - vertex 3.482020e+001 1.087460e+000 2.180922e+000 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 3.482020e+001 1.087460e+000 2.180922e+000 - vertex 3.482020e+001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 1.989763e+000 2.701867e+000 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 3.482020e+001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 1.989763e+000 2.701867e+000 - vertex 3.482020e+001 4.150665e+000 6.093379e-001 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 1.989763e+000 2.701867e+000 - vertex 3.482020e+001 2.359533e+000 3.071637e+000 - vertex 3.482020e+001 4.150665e+000 6.093379e-001 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 4.150665e+000 6.093379e-001 - vertex 3.482020e+001 2.359533e+000 3.071637e+000 - vertex 3.482020e+001 4.813319e+000 1.336768e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 4.813319e+000 1.336768e+000 - vertex 3.482020e+001 2.359533e+000 3.071637e+000 - vertex 3.482020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.348164e+000 2.162726e+000 - vertex 3.482020e+001 2.659476e+000 3.500000e+000 - vertex 3.482020e+001 2.880478e+000 3.973940e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.740815e+000 3.064995e+000 - vertex 3.482020e+001 2.880478e+000 3.973940e+000 - vertex 3.482020e+001 3.015823e+000 4.479055e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.061400e+000 5.000000e+000 - vertex 3.482020e+001 3.015823e+000 4.479055e+000 - vertex 3.482020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 3.015823e+000 5.520945e+000 - vertex 3.482020e+001 5.061400e+000 5.000000e+000 - vertex 3.482020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 3.015823e+000 5.520945e+000 - vertex 3.482020e+001 4.985439e+000 5.868241e+000 - vertex 3.482020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 3.015823e+000 5.520945e+000 - vertex 3.482020e+001 2.880478e+000 6.026060e+000 - vertex 3.482020e+001 4.985439e+000 5.868241e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 4.985439e+000 5.868241e+000 - vertex 3.482020e+001 2.880478e+000 6.026060e+000 - vertex 3.482020e+001 4.759863e+000 6.710101e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 4.759863e+000 6.710101e+000 - vertex 3.482020e+001 2.880478e+000 6.026060e+000 - vertex 3.482020e+001 2.659476e+000 6.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 4.391527e+000 7.500000e+000 - vertex 3.482020e+001 2.659476e+000 6.500000e+000 - vertex 3.482020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 3.891622e+000 8.213938e+000 - vertex 3.482020e+001 2.359533e+000 6.928363e+000 - vertex 3.482020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 3.275338e+000 8.830222e+000 - vertex 3.482020e+001 1.989763e+000 7.298133e+000 - vertex 3.482020e+001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 3.275338e+000 8.830222e+000 - vertex 3.482020e+001 3.891622e+000 8.213938e+000 - vertex 3.482020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 1.989763e+000 7.298133e+000 - vertex 3.482020e+001 1.561400e+000 7.598076e+000 - vertex 3.482020e+001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 2.561400e+000 9.330127e+000 - vertex 3.482020e+001 1.561400e+000 7.598076e+000 - vertex 3.482020e+001 1.771501e+000 9.698463e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 1.771501e+000 9.698463e+000 - vertex 3.482020e+001 1.561400e+000 7.598076e+000 - vertex 3.482020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 9.296409e-001 9.924039e+000 - vertex 3.482020e+001 1.087460e+000 7.819078e+000 - vertex 3.482020e+001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 6.140000e-002 1.000000e+001 - vertex 3.482020e+001 5.823445e-001 7.954423e+000 - vertex 3.482020e+001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -8.068409e-001 9.924039e+000 - vertex 3.482020e+001 6.140000e-002 8.000000e+000 - vertex 3.482020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -1.648701e+000 9.698463e+000 - vertex 3.482020e+001 -4.595445e-001 7.954423e+000 - vertex 3.482020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.438600e+000 9.330127e+000 - vertex 3.482020e+001 -9.646604e-001 7.819078e+000 - vertex 3.482020e+001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -3.152538e+000 8.830222e+000 - vertex 3.482020e+001 -1.438600e+000 7.598076e+000 - vertex 3.482020e+001 -1.866963e+000 7.298133e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.236733e+000 6.928363e+000 - vertex 3.482020e+001 -3.152538e+000 8.830222e+000 - vertex 3.482020e+001 -1.866963e+000 7.298133e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.236733e+000 6.928363e+000 - vertex 3.482020e+001 -3.768822e+000 8.213938e+000 - vertex 3.482020e+001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.236733e+000 6.928363e+000 - vertex 3.482020e+001 -2.536676e+000 6.500000e+000 - vertex 3.482020e+001 -3.768822e+000 8.213938e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -3.768822e+000 8.213938e+000 - vertex 3.482020e+001 -2.536676e+000 6.500000e+000 - vertex 3.482020e+001 -4.268727e+000 7.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.268727e+000 7.500000e+000 - vertex 3.482020e+001 -2.536676e+000 6.500000e+000 - vertex 3.482020e+001 -2.757678e+000 6.026060e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.637063e+000 6.710101e+000 - vertex 3.482020e+001 -2.757678e+000 6.026060e+000 - vertex 3.482020e+001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.862639e+000 5.868241e+000 - vertex 3.482020e+001 -2.893023e+000 5.520945e+000 - vertex 3.482020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.938600e+000 5.000000e+000 - vertex 3.482020e+001 -4.862639e+000 5.868241e+000 - vertex 3.482020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.061400e+000 5.000000e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 3.482020e+001 5.980711e+000 4.019309e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.740815e+000 3.064995e+000 - vertex 3.482020e+001 5.061400e+000 5.000000e+000 - vertex 3.482020e+001 5.980711e+000 4.019309e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.740815e+000 3.064995e+000 - vertex 3.482020e+001 3.015823e+000 4.479055e+000 - vertex 3.482020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.740815e+000 3.064995e+000 - vertex 3.482020e+001 5.348164e+000 2.162726e+000 - vertex 3.482020e+001 2.880478e+000 3.973940e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 5.348164e+000 2.162726e+000 - vertex 3.482020e+001 4.813319e+000 1.336768e+000 - vertex 3.482020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 6.140000e-002 0.000000e+000 - vertex 3.482020e+001 -8.068409e-001 7.596123e-002 - vertex 3.482020e+001 -4.595445e-001 2.045577e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -1.648701e+000 3.015369e-001 - vertex 3.482020e+001 -9.646604e-001 2.180922e+000 - vertex 3.482020e+001 -8.068409e-001 7.596123e-002 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -3.768822e+000 1.786062e+000 - vertex 3.482020e+001 -4.268727e+000 2.500000e+000 - vertex 3.482020e+001 -2.236733e+000 3.071637e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.268727e+000 2.500000e+000 - vertex 3.482020e+001 -4.637063e+000 3.289899e+000 - vertex 3.482020e+001 -2.536676e+000 3.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.862639e+000 5.868241e+000 - vertex 3.482020e+001 -4.637063e+000 6.710101e+000 - vertex 3.482020e+001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -4.637063e+000 6.710101e+000 - vertex 3.482020e+001 -4.268727e+000 7.500000e+000 - vertex 3.482020e+001 -2.757678e+000 6.026060e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -3.152538e+000 8.830222e+000 - vertex 3.482020e+001 -2.438600e+000 9.330127e+000 - vertex 3.482020e+001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -2.438600e+000 9.330127e+000 - vertex 3.482020e+001 -1.648701e+000 9.698463e+000 - vertex 3.482020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 -1.648701e+000 9.698463e+000 - vertex 3.482020e+001 -8.068409e-001 9.924039e+000 - vertex 3.482020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 6.140000e-002 1.000000e+001 - vertex 3.482020e+001 6.140000e-002 8.000000e+000 - vertex 3.482020e+001 -8.068409e-001 9.924039e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 9.296409e-001 9.924039e+000 - vertex 3.482020e+001 5.823445e-001 7.954423e+000 - vertex 3.482020e+001 6.140000e-002 1.000000e+001 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 1.771501e+000 9.698463e+000 - vertex 3.482020e+001 1.087460e+000 7.819078e+000 - vertex 3.482020e+001 9.296409e-001 9.924039e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 2.359533e+000 6.928363e+000 - vertex 3.482020e+001 3.891622e+000 8.213938e+000 - vertex 3.482020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 3.482020e+001 4.759863e+000 6.710101e+000 - vertex 3.482020e+001 2.659476e+000 6.500000e+000 - vertex 3.482020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.966323e-001 8.200039e-002 - outer loop - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex 1.482020e+001 5.980711e+000 4.019309e+000 - endloop - endfacet - facet normal -4.306895e-017 -9.698266e-001 2.437957e-001 - outer loop - vertex 3.482020e+001 5.980711e+000 4.019309e+000 - vertex 1.482020e+001 5.980711e+000 4.019309e+000 - vertex 3.482020e+001 5.740815e+000 3.064995e+000 - endloop - endfacet - facet normal -4.425936e-017 -9.966323e-001 8.200039e-002 - outer loop - vertex 3.482020e+001 5.980711e+000 4.019309e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 1.482020e+001 5.980711e+000 4.019309e+000 - endloop - endfacet - facet normal 1.692405e-017 -9.698266e-001 2.437957e-001 - outer loop - vertex 1.482020e+001 5.980711e+000 4.019309e+000 - vertex 1.482020e+001 5.740815e+000 3.064995e+000 - vertex 3.482020e+001 5.740815e+000 3.064995e+000 - endloop - endfacet - facet normal -3.581497e-018 -9.169362e-001 3.990338e-001 - outer loop - vertex 3.482020e+001 5.740815e+000 3.064995e+000 - vertex 1.482020e+001 5.740815e+000 3.064995e+000 - vertex 3.482020e+001 5.348164e+000 2.162726e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.169362e-001 3.990338e-001 - outer loop - vertex 3.482020e+001 5.348164e+000 2.162726e+000 - vertex 1.482020e+001 5.740815e+000 3.064995e+000 - vertex 1.482020e+001 5.348164e+000 2.162726e+000 - endloop - endfacet - facet normal 1.313813e-017 -8.393837e-001 5.435393e-001 - outer loop - vertex 3.482020e+001 4.813319e+000 1.336768e+000 - vertex 1.482020e+001 5.348164e+000 2.162726e+000 - vertex 1.482020e+001 4.813319e+000 1.336768e+000 - endloop - endfacet - facet normal 0.000000e+000 -7.392549e-001 6.734257e-001 - outer loop - vertex 3.482020e+001 4.150665e+000 6.093379e-001 - vertex 1.482020e+001 4.813319e+000 1.336768e+000 - vertex 1.482020e+001 4.150665e+000 6.093379e-001 - endloop - endfacet - facet normal 0.000000e+000 -6.192429e-001 7.851995e-001 - outer loop - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 1.482020e+001 4.150665e+000 6.093379e-001 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 -6.192429e-001 7.851995e-001 - outer loop - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 3.482020e+001 4.150665e+000 6.093379e-001 - vertex 1.482020e+001 4.150665e+000 6.093379e-001 - endloop - endfacet - facet normal 2.820675e-018 -7.392549e-001 6.734257e-001 - outer loop - vertex 3.482020e+001 4.150665e+000 6.093379e-001 - vertex 3.482020e+001 4.813319e+000 1.336768e+000 - vertex 1.482020e+001 4.813319e+000 1.336768e+000 - endloop - endfacet - facet normal 0.000000e+000 -8.393837e-001 5.435393e-001 - outer loop - vertex 3.482020e+001 4.813319e+000 1.336768e+000 - vertex 3.482020e+001 5.348164e+000 2.162726e+000 - vertex 1.482020e+001 5.348164e+000 2.162726e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -2.893023e+000 5.520945e+000 - vertex 1.482020e+001 -4.862639e+000 5.868241e+000 - vertex 1.482020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -2.893023e+000 5.520945e+000 - vertex 1.482020e+001 -4.637063e+000 6.710101e+000 - vertex 1.482020e+001 -4.862639e+000 5.868241e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -2.893023e+000 5.520945e+000 - vertex 1.482020e+001 -2.757678e+000 6.026060e+000 - vertex 1.482020e+001 -4.637063e+000 6.710101e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.637063e+000 6.710101e+000 - vertex 1.482020e+001 -2.757678e+000 6.026060e+000 - vertex 1.482020e+001 -4.268727e+000 7.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.268727e+000 7.500000e+000 - vertex 1.482020e+001 -2.757678e+000 6.026060e+000 - vertex 1.482020e+001 -2.536676e+000 6.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -3.768822e+000 8.213938e+000 - vertex 1.482020e+001 -2.536676e+000 6.500000e+000 - vertex 1.482020e+001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -1.866963e+000 7.298133e+000 - vertex 1.482020e+001 -3.768822e+000 8.213938e+000 - vertex 1.482020e+001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -1.866963e+000 7.298133e+000 - vertex 1.482020e+001 -3.152538e+000 8.830222e+000 - vertex 1.482020e+001 -3.768822e+000 8.213938e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -1.866963e+000 7.298133e+000 - vertex 1.482020e+001 -1.438600e+000 7.598076e+000 - vertex 1.482020e+001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -3.152538e+000 8.830222e+000 - vertex 1.482020e+001 -1.438600e+000 7.598076e+000 - vertex 1.482020e+001 -2.438600e+000 9.330127e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -2.438600e+000 9.330127e+000 - vertex 1.482020e+001 -1.438600e+000 7.598076e+000 - vertex 1.482020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -1.648701e+000 9.698463e+000 - vertex 1.482020e+001 -9.646604e-001 7.819078e+000 - vertex 1.482020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -8.068409e-001 9.924039e+000 - vertex 1.482020e+001 -4.595445e-001 7.954423e+000 - vertex 1.482020e+001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 6.140000e-002 1.000000e+001 - vertex 1.482020e+001 6.140000e-002 8.000000e+000 - vertex 1.482020e+001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 9.296409e-001 9.924039e+000 - vertex 1.482020e+001 5.823445e-001 7.954423e+000 - vertex 1.482020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 1.771501e+000 9.698463e+000 - vertex 1.482020e+001 1.087460e+000 7.819078e+000 - vertex 1.482020e+001 1.561400e+000 7.598076e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 2.561400e+000 9.330127e+000 - vertex 1.482020e+001 1.561400e+000 7.598076e+000 - vertex 1.482020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 3.275338e+000 8.830222e+000 - vertex 1.482020e+001 1.989763e+000 7.298133e+000 - vertex 1.482020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 3.891622e+000 8.213938e+000 - vertex 1.482020e+001 2.359533e+000 6.928363e+000 - vertex 1.482020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 3.891622e+000 8.213938e+000 - vertex 1.482020e+001 3.275338e+000 8.830222e+000 - vertex 1.482020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 2.659476e+000 6.500000e+000 - vertex 1.482020e+001 4.391527e+000 7.500000e+000 - vertex 1.482020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 2.659476e+000 6.500000e+000 - vertex 1.482020e+001 4.759863e+000 6.710101e+000 - vertex 1.482020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 2.659476e+000 6.500000e+000 - vertex 1.482020e+001 2.880478e+000 6.026060e+000 - vertex 1.482020e+001 4.759863e+000 6.710101e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 4.759863e+000 6.710101e+000 - vertex 1.482020e+001 2.880478e+000 6.026060e+000 - vertex 1.482020e+001 4.985439e+000 5.868241e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 4.985439e+000 5.868241e+000 - vertex 1.482020e+001 2.880478e+000 6.026060e+000 - vertex 1.482020e+001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - vertex 1.482020e+001 3.015823e+000 5.520945e+000 - vertex 1.482020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 3.015823e+000 4.479055e+000 - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - vertex 1.482020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 3.015823e+000 4.479055e+000 - vertex 1.482020e+001 5.740815e+000 3.064995e+000 - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 3.015823e+000 4.479055e+000 - vertex 1.482020e+001 2.880478e+000 3.973940e+000 - vertex 1.482020e+001 5.740815e+000 3.064995e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 5.740815e+000 3.064995e+000 - vertex 1.482020e+001 2.880478e+000 3.973940e+000 - vertex 1.482020e+001 5.348164e+000 2.162726e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 5.348164e+000 2.162726e+000 - vertex 1.482020e+001 2.880478e+000 3.973940e+000 - vertex 1.482020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 4.813319e+000 1.336768e+000 - vertex 1.482020e+001 2.659476e+000 3.500000e+000 - vertex 1.482020e+001 2.359533e+000 3.071637e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 4.150665e+000 6.093379e-001 - vertex 1.482020e+001 2.359533e+000 3.071637e+000 - vertex 1.482020e+001 1.989763e+000 2.701867e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 1.482020e+001 1.989763e+000 2.701867e+000 - vertex 1.482020e+001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 1.087460e+000 2.180922e+000 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 1.482020e+001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 1.087460e+000 2.180922e+000 - vertex 1.482020e+001 6.140000e-002 0.000000e+000 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 1.087460e+000 2.180922e+000 - vertex 1.482020e+001 5.823445e-001 2.045577e+000 - vertex 1.482020e+001 6.140000e-002 0.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 6.140000e-002 0.000000e+000 - vertex 1.482020e+001 5.823445e-001 2.045577e+000 - vertex 1.482020e+001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.595445e-001 2.045577e+000 - vertex 1.482020e+001 6.140000e-002 0.000000e+000 - vertex 1.482020e+001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.595445e-001 2.045577e+000 - vertex 1.482020e+001 -8.068409e-001 7.596123e-002 - vertex 1.482020e+001 6.140000e-002 0.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.595445e-001 2.045577e+000 - vertex 1.482020e+001 -9.646604e-001 2.180922e+000 - vertex 1.482020e+001 -8.068409e-001 7.596123e-002 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -8.068409e-001 7.596123e-002 - vertex 1.482020e+001 -9.646604e-001 2.180922e+000 - vertex 1.482020e+001 -1.648701e+000 3.015369e-001 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -1.648701e+000 3.015369e-001 - vertex 1.482020e+001 -9.646604e-001 2.180922e+000 - vertex 1.482020e+001 -1.438600e+000 2.401924e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -2.438600e+000 6.698730e-001 - vertex 1.482020e+001 -1.438600e+000 2.401924e+000 - vertex 1.482020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -3.152538e+000 1.169778e+000 - vertex 1.482020e+001 -1.866963e+000 2.701867e+000 - vertex 1.482020e+001 -2.236733e+000 3.071637e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -3.768822e+000 1.786062e+000 - vertex 1.482020e+001 -2.236733e+000 3.071637e+000 - vertex 1.482020e+001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -3.768822e+000 1.786062e+000 - vertex 1.482020e+001 -3.152538e+000 1.169778e+000 - vertex 1.482020e+001 -2.236733e+000 3.071637e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -2.236733e+000 3.071637e+000 - vertex 1.482020e+001 -2.536676e+000 3.500000e+000 - vertex 1.482020e+001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.268727e+000 2.500000e+000 - vertex 1.482020e+001 -2.536676e+000 3.500000e+000 - vertex 1.482020e+001 -4.637063e+000 3.289899e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.637063e+000 3.289899e+000 - vertex 1.482020e+001 -2.536676e+000 3.500000e+000 - vertex 1.482020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.862639e+000 4.131759e+000 - vertex 1.482020e+001 -2.757678e+000 3.973940e+000 - vertex 1.482020e+001 -2.893023e+000 4.479055e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.938600e+000 5.000000e+000 - vertex 1.482020e+001 -2.893023e+000 4.479055e+000 - vertex 1.482020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.862639e+000 5.868241e+000 - vertex 1.482020e+001 -4.938600e+000 5.000000e+000 - vertex 1.482020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - vertex 1.482020e+001 5.980711e+000 4.019309e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 5.980711e+000 4.019309e+000 - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - vertex 1.482020e+001 5.740815e+000 3.064995e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - vertex 1.482020e+001 4.985439e+000 5.868241e+000 - vertex 1.482020e+001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 2.561400e+000 9.330127e+000 - vertex 1.482020e+001 1.989763e+000 7.298133e+000 - vertex 1.482020e+001 3.275338e+000 8.830222e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 2.561400e+000 9.330127e+000 - vertex 1.482020e+001 1.771501e+000 9.698463e+000 - vertex 1.482020e+001 1.561400e+000 7.598076e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 1.771501e+000 9.698463e+000 - vertex 1.482020e+001 9.296409e-001 9.924039e+000 - vertex 1.482020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 6.140000e-002 1.000000e+001 - vertex 1.482020e+001 5.823445e-001 7.954423e+000 - vertex 1.482020e+001 9.296409e-001 9.924039e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -8.068409e-001 9.924039e+000 - vertex 1.482020e+001 6.140000e-002 8.000000e+000 - vertex 1.482020e+001 6.140000e-002 1.000000e+001 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -8.068409e-001 9.924039e+000 - vertex 1.482020e+001 -1.648701e+000 9.698463e+000 - vertex 1.482020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -1.648701e+000 9.698463e+000 - vertex 1.482020e+001 -2.438600e+000 9.330127e+000 - vertex 1.482020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -3.768822e+000 8.213938e+000 - vertex 1.482020e+001 -4.268727e+000 7.500000e+000 - vertex 1.482020e+001 -2.536676e+000 6.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.938600e+000 5.000000e+000 - vertex 1.482020e+001 -4.862639e+000 4.131759e+000 - vertex 1.482020e+001 -2.893023e+000 4.479055e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -4.862639e+000 4.131759e+000 - vertex 1.482020e+001 -4.637063e+000 3.289899e+000 - vertex 1.482020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -2.438600e+000 6.698730e-001 - vertex 1.482020e+001 -1.866963e+000 2.701867e+000 - vertex 1.482020e+001 -3.152538e+000 1.169778e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 -2.438600e+000 6.698730e-001 - vertex 1.482020e+001 -1.648701e+000 3.015369e-001 - vertex 1.482020e+001 -1.438600e+000 2.401924e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 1.482020e+001 4.150665e+000 6.093379e-001 - vertex 1.482020e+001 1.989763e+000 2.701867e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 4.150665e+000 6.093379e-001 - vertex 1.482020e+001 4.813319e+000 1.336768e+000 - vertex 1.482020e+001 2.359533e+000 3.071637e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 1.482020e+001 4.813319e+000 1.336768e+000 - vertex 1.482020e+001 5.348164e+000 2.162726e+000 - vertex 1.482020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.832020e+001 1.706140e+001 5.000000e+000 - vertex 3.837337e+001 1.766917e+001 5.000000e+000 - vertex 2.657020e+001 1.609249e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.706996e+001 1.574256e+001 5.000000e+000 - vertex 3.832020e+001 1.706140e+001 5.000000e+000 - vertex 2.657020e+001 1.609249e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.706996e+001 1.574256e+001 5.000000e+000 - vertex 3.837337e+001 1.645363e+001 5.000000e+000 - vertex 3.832020e+001 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.706996e+001 1.574256e+001 5.000000e+000 - vertex 2.750136e+001 1.531116e+001 5.000000e+000 - vertex 3.837337e+001 1.645363e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.837337e+001 1.645363e+001 5.000000e+000 - vertex 2.750136e+001 1.531116e+001 5.000000e+000 - vertex 3.853128e+001 1.586433e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.853128e+001 1.586433e+001 5.000000e+000 - vertex 2.750136e+001 1.531116e+001 5.000000e+000 - vertex 2.785129e+001 1.481140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.878911e+001 1.531140e+001 5.000000e+000 - vertex 2.785129e+001 1.481140e+001 5.000000e+000 - vertex 2.810912e+001 1.425847e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.913904e+001 1.481164e+001 5.000000e+000 - vertex 2.810912e+001 1.425847e+001 5.000000e+000 - vertex 2.826703e+001 1.366917e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.957044e+001 1.438024e+001 5.000000e+000 - vertex 2.826703e+001 1.366917e+001 5.000000e+000 - vertex 2.832020e+001 1.306140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.007020e+001 1.403031e+001 5.000000e+000 - vertex 2.832020e+001 1.306140e+001 5.000000e+000 - vertex 2.826703e+001 1.245363e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.062313e+001 1.377248e+001 5.000000e+000 - vertex 2.826703e+001 1.245363e+001 5.000000e+000 - vertex 2.810912e+001 1.186433e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.785129e+001 1.131140e+001 5.000000e+000 - vertex 4.062313e+001 1.377248e+001 5.000000e+000 - vertex 2.810912e+001 1.186433e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.785129e+001 1.131140e+001 5.000000e+000 - vertex 4.121243e+001 1.361457e+001 5.000000e+000 - vertex 4.062313e+001 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.785129e+001 1.131140e+001 5.000000e+000 - vertex 2.750136e+001 1.081164e+001 5.000000e+000 - vertex 4.121243e+001 1.361457e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.121243e+001 1.361457e+001 5.000000e+000 - vertex 2.750136e+001 1.081164e+001 5.000000e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.182020e+001 1.356140e+001 5.000000e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.242797e+001 1.361457e+001 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.301727e+001 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.242797e+001 1.361457e+001 5.000000e+000 - vertex 4.182020e+001 1.356140e+001 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.837337e+001 1.766917e+001 5.000000e+000 - vertex 3.853128e+001 1.825847e+001 5.000000e+000 - vertex 2.601727e+001 1.635032e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.657020e+001 1.609249e+001 5.000000e+000 - vertex 3.837337e+001 1.766917e+001 5.000000e+000 - vertex 2.601727e+001 1.635032e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.878911e+001 1.881140e+001 5.000000e+000 - vertex 2.601727e+001 1.635032e+001 5.000000e+000 - vertex 3.853128e+001 1.825847e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.878911e+001 1.881140e+001 5.000000e+000 - vertex 2.542797e+001 1.650823e+001 5.000000e+000 - vertex 2.601727e+001 1.635032e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.878911e+001 1.881140e+001 5.000000e+000 - vertex 3.913904e+001 1.931116e+001 5.000000e+000 - vertex 2.542797e+001 1.650823e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.542797e+001 1.650823e+001 5.000000e+000 - vertex 3.913904e+001 1.931116e+001 5.000000e+000 - vertex 3.957044e+001 1.974256e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.482020e+001 1.656140e+001 5.000000e+000 - vertex 3.957044e+001 1.974256e+001 5.000000e+000 - vertex 4.007020e+001 2.009249e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 9.570200e+000 2.009249e+001 5.000000e+000 - vertex 4.007020e+001 2.009249e+001 5.000000e+000 - vertex 9.017271e+000 2.035032e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 9.570200e+000 2.009249e+001 5.000000e+000 - vertex 2.482020e+001 1.656140e+001 5.000000e+000 - vertex 4.007020e+001 2.009249e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 9.570200e+000 2.009249e+001 5.000000e+000 - vertex 1.006996e+001 1.974256e+001 5.000000e+000 - vertex 2.482020e+001 1.656140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.482020e+001 1.656140e+001 5.000000e+000 - vertex 1.006996e+001 1.974256e+001 5.000000e+000 - vertex 2.421243e+001 1.650823e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.421243e+001 1.650823e+001 5.000000e+000 - vertex 1.006996e+001 1.974256e+001 5.000000e+000 - vertex 1.050136e+001 1.931116e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 1.085129e+001 1.881140e+001 5.000000e+000 - vertex 2.421243e+001 1.650823e+001 5.000000e+000 - vertex 1.050136e+001 1.931116e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 1.085129e+001 1.881140e+001 5.000000e+000 - vertex 2.362313e+001 1.635032e+001 5.000000e+000 - vertex 2.421243e+001 1.650823e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 1.085129e+001 1.881140e+001 5.000000e+000 - vertex 1.110912e+001 1.825847e+001 5.000000e+000 - vertex 2.362313e+001 1.635032e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.362313e+001 1.635032e+001 5.000000e+000 - vertex 1.110912e+001 1.825847e+001 5.000000e+000 - vertex 1.126703e+001 1.766917e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.307020e+001 1.609249e+001 5.000000e+000 - vertex 1.126703e+001 1.766917e+001 5.000000e+000 - vertex 1.132020e+001 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.257044e+001 1.574256e+001 5.000000e+000 - vertex 1.132020e+001 1.706140e+001 5.000000e+000 - vertex 1.126703e+001 1.645363e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.213904e+001 1.531116e+001 5.000000e+000 - vertex 1.126703e+001 1.645363e+001 5.000000e+000 - vertex 1.110912e+001 1.586433e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.178911e+001 1.481140e+001 5.000000e+000 - vertex 1.110912e+001 1.586433e+001 5.000000e+000 - vertex 1.085129e+001 1.531140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.153128e+001 1.425847e+001 5.000000e+000 - vertex 1.085129e+001 1.531140e+001 5.000000e+000 - vertex 1.050136e+001 1.481164e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.137337e+001 1.366917e+001 5.000000e+000 - vertex 1.050136e+001 1.481164e+001 5.000000e+000 - vertex 1.006996e+001 1.438024e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.132020e+001 1.306140e+001 5.000000e+000 - vertex 1.006996e+001 1.438024e+001 5.000000e+000 - vertex 9.570200e+000 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.137337e+001 1.245363e+001 5.000000e+000 - vertex 9.570200e+000 1.403031e+001 5.000000e+000 - vertex 9.017271e+000 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.153128e+001 1.186433e+001 5.000000e+000 - vertex 9.017271e+000 1.377248e+001 5.000000e+000 - vertex 2.178911e+001 1.131140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.153128e+001 1.186433e+001 5.000000e+000 - vertex 2.137337e+001 1.245363e+001 5.000000e+000 - vertex 9.017271e+000 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.007020e+001 2.009249e+001 5.000000e+000 - vertex 4.062313e+001 2.035032e+001 5.000000e+000 - vertex 9.017271e+000 2.035032e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 9.017271e+000 2.035032e+001 5.000000e+000 - vertex 4.062313e+001 2.035032e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 8.427969e+000 2.050823e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 7.820200e+000 2.056140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 8.427969e+000 2.050823e+001 5.000000e+000 - vertex 9.017271e+000 2.035032e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.121243e+001 2.050823e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.062313e+001 2.035032e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.121243e+001 2.050823e+001 5.000000e+000 - vertex 4.182020e+001 2.056140e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.182020e+001 2.056140e+001 5.000000e+000 - vertex 4.242797e+001 2.050823e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.301727e+001 2.035032e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.242797e+001 2.050823e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.301727e+001 2.035032e+001 5.000000e+000 - vertex 4.357020e+001 2.009249e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.357020e+001 2.009249e+001 5.000000e+000 - vertex 4.406996e+001 1.974256e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.450136e+001 1.931116e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.406996e+001 1.974256e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.450136e+001 1.931116e+001 5.000000e+000 - vertex 4.485129e+001 1.881140e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.485129e+001 1.881140e+001 5.000000e+000 - vertex 4.510912e+001 1.825847e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.526703e+001 1.766917e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.510912e+001 1.825847e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.526703e+001 1.766917e+001 5.000000e+000 - vertex 4.532020e+001 1.706140e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.532020e+001 1.706140e+001 5.000000e+000 - vertex 4.526703e+001 1.645363e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.526703e+001 1.645363e+001 5.000000e+000 - vertex 4.510912e+001 1.586433e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.485129e+001 1.531140e+001 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.510912e+001 1.586433e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.485129e+001 1.531140e+001 5.000000e+000 - vertex 4.450136e+001 1.481164e+001 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.450136e+001 1.481164e+001 5.000000e+000 - vertex 4.406996e+001 1.438024e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.357020e+001 1.403031e+001 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.406996e+001 1.438024e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.357020e+001 1.403031e+001 5.000000e+000 - vertex 4.301727e+001 1.377248e+001 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.121243e+001 1.361457e+001 5.000000e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 4.182020e+001 1.356140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.062313e+001 1.377248e+001 5.000000e+000 - vertex 4.007020e+001 1.403031e+001 5.000000e+000 - vertex 2.826703e+001 1.245363e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.957044e+001 1.438024e+001 5.000000e+000 - vertex 2.832020e+001 1.306140e+001 5.000000e+000 - vertex 4.007020e+001 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.957044e+001 1.438024e+001 5.000000e+000 - vertex 3.913904e+001 1.481164e+001 5.000000e+000 - vertex 2.826703e+001 1.366917e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.878911e+001 1.531140e+001 5.000000e+000 - vertex 2.810912e+001 1.425847e+001 5.000000e+000 - vertex 3.913904e+001 1.481164e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.878911e+001 1.531140e+001 5.000000e+000 - vertex 3.853128e+001 1.586433e+001 5.000000e+000 - vertex 2.785129e+001 1.481140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.137337e+001 1.366917e+001 5.000000e+000 - vertex 1.006996e+001 1.438024e+001 5.000000e+000 - vertex 2.132020e+001 1.306140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.137337e+001 1.366917e+001 5.000000e+000 - vertex 2.153128e+001 1.425847e+001 5.000000e+000 - vertex 1.050136e+001 1.481164e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.178911e+001 1.481140e+001 5.000000e+000 - vertex 1.085129e+001 1.531140e+001 5.000000e+000 - vertex 2.153128e+001 1.425847e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.213904e+001 1.531116e+001 5.000000e+000 - vertex 1.110912e+001 1.586433e+001 5.000000e+000 - vertex 2.178911e+001 1.481140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.213904e+001 1.531116e+001 5.000000e+000 - vertex 2.257044e+001 1.574256e+001 5.000000e+000 - vertex 1.126703e+001 1.645363e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.257044e+001 1.574256e+001 5.000000e+000 - vertex 2.307020e+001 1.609249e+001 5.000000e+000 - vertex 1.132020e+001 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.307020e+001 1.609249e+001 5.000000e+000 - vertex 2.362313e+001 1.635032e+001 5.000000e+000 - vertex 1.126703e+001 1.766917e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.482020e+001 1.656140e+001 5.000000e+000 - vertex 2.542797e+001 1.650823e+001 5.000000e+000 - vertex 3.957044e+001 1.974256e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.750136e+001 1.081164e+001 5.000000e+000 - vertex 2.706996e+001 1.038024e+001 5.000000e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 2.706996e+001 1.038024e+001 5.000000e+000 - vertex 2.657020e+001 1.003031e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.601727e+001 9.772476e+000 5.000000e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 2.657020e+001 1.003031e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.601727e+001 9.772476e+000 5.000000e+000 - vertex 2.542797e+001 9.614573e+000 5.000000e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 2.542797e+001 9.614573e+000 5.000000e+000 - vertex 2.482020e+001 9.561400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex 2.482020e+001 9.561400e+000 5.000000e+000 - vertex 2.421243e+001 9.614573e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.362313e+001 9.772476e+000 5.000000e+000 - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex 2.421243e+001 9.614573e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.362313e+001 9.772476e+000 5.000000e+000 - vertex 2.307020e+001 1.003031e+001 5.000000e+000 - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex 2.307020e+001 1.003031e+001 5.000000e+000 - vertex 2.257044e+001 1.038024e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.213904e+001 1.081164e+001 5.000000e+000 - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex 2.257044e+001 1.038024e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.213904e+001 1.081164e+001 5.000000e+000 - vertex 8.427969e+000 1.361457e+001 5.000000e+000 - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.213904e+001 1.081164e+001 5.000000e+000 - vertex 2.178911e+001 1.131140e+001 5.000000e+000 - vertex 8.427969e+000 1.361457e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 8.427969e+000 1.361457e+001 5.000000e+000 - vertex 2.178911e+001 1.131140e+001 5.000000e+000 - vertex 9.017271e+000 1.377248e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 2.132020e+001 1.306140e+001 5.000000e+000 - vertex 9.570200e+000 1.403031e+001 5.000000e+000 - vertex 2.137337e+001 1.245363e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.373373e+000 1.766917e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 4.320200e+000 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.373373e+000 1.766917e+001 5.000000e+000 - vertex 4.531276e+000 1.825847e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 4.531276e+000 1.825847e+001 5.000000e+000 - vertex 4.789111e+000 1.881140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 5.139044e+000 1.931116e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 4.789111e+000 1.881140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 5.139044e+000 1.931116e+001 5.000000e+000 - vertex 5.570443e+000 1.974256e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 5.570443e+000 1.974256e+001 5.000000e+000 - vertex 6.070200e+000 2.009249e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 6.623129e+000 2.035032e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 6.070200e+000 2.009249e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 6.623129e+000 2.035032e+001 5.000000e+000 - vertex 7.212431e+000 2.050823e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 7.212431e+000 2.050823e+001 5.000000e+000 - vertex 7.820200e+000 2.056140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 8.427969e+000 1.361457e+001 5.000000e+000 - vertex 7.820200e+000 1.356140e+001 5.000000e+000 - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex 7.820200e+000 1.356140e+001 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 7.212431e+000 1.361457e+001 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex 7.820200e+000 1.356140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 7.212431e+000 1.361457e+001 5.000000e+000 - vertex 6.623129e+000 1.377248e+001 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex 6.623129e+000 1.377248e+001 5.000000e+000 - vertex 6.070200e+000 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 5.570443e+000 1.438024e+001 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex 6.070200e+000 1.403031e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 5.570443e+000 1.438024e+001 5.000000e+000 - vertex 5.139044e+000 1.481164e+001 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex 5.139044e+000 1.481164e+001 5.000000e+000 - vertex 4.789111e+000 1.531140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.531276e+000 1.586433e+001 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex 4.789111e+000 1.531140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.531276e+000 1.586433e+001 5.000000e+000 - vertex 4.373373e+000 1.645363e+001 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex 4.373373e+000 1.645363e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 4.373373e+000 1.645363e+001 5.000000e+000 - vertex 4.320200e+000 1.706140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 1.482020e+001 6.061400e+000 5.000000e+000 - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 2.482020e+001 9.561400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 3.482020e+001 6.061400e+000 5.000000e+000 - vertex 3.482020e+001 5.061400e+000 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.526703e+001 1.645363e+001 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 4.062313e+001 2.035032e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 9.961947e-001 8.715574e-002 - outer loop - vertex 3.482020e+001 5.061400e+000 5.000000e+000 - vertex 3.482020e+001 4.985439e+000 5.868241e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 9.961947e-001 8.715574e-002 - outer loop - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 3.482020e+001 4.985439e+000 5.868241e+000 - vertex 4.982020e+001 4.985439e+000 5.868241e+000 - endloop - endfacet - facet normal 0.000000e+000 9.659258e-001 2.588190e-001 - outer loop - vertex 4.982020e+001 4.985439e+000 5.868241e+000 - vertex 3.482020e+001 4.985439e+000 5.868241e+000 - vertex 3.482020e+001 4.759863e+000 6.710101e+000 - endloop - endfacet - facet normal 0.000000e+000 9.063078e-001 4.226183e-001 - outer loop - vertex 4.982020e+001 4.759863e+000 6.710101e+000 - vertex 3.482020e+001 4.759863e+000 6.710101e+000 - vertex 3.482020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 8.191520e-001 5.735764e-001 - outer loop - vertex 4.982020e+001 4.391527e+000 7.500000e+000 - vertex 3.482020e+001 4.391527e+000 7.500000e+000 - vertex 3.482020e+001 3.891622e+000 8.213938e+000 - endloop - endfacet - facet normal 0.000000e+000 7.071068e-001 7.071068e-001 - outer loop - vertex 4.982020e+001 3.891622e+000 8.213938e+000 - vertex 3.482020e+001 3.891622e+000 8.213938e+000 - vertex 3.482020e+001 3.275338e+000 8.830222e+000 - endloop - endfacet - facet normal 0.000000e+000 5.735764e-001 8.191520e-001 - outer loop - vertex 4.982020e+001 3.275338e+000 8.830222e+000 - vertex 3.482020e+001 3.275338e+000 8.830222e+000 - vertex 3.482020e+001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal 0.000000e+000 4.226183e-001 9.063078e-001 - outer loop - vertex 4.982020e+001 2.561400e+000 9.330127e+000 - vertex 3.482020e+001 2.561400e+000 9.330127e+000 - vertex 3.482020e+001 1.771501e+000 9.698463e+000 - endloop - endfacet - facet normal 0.000000e+000 2.588190e-001 9.659258e-001 - outer loop - vertex 4.982020e+001 1.771501e+000 9.698463e+000 - vertex 3.482020e+001 1.771501e+000 9.698463e+000 - vertex 3.482020e+001 9.296409e-001 9.924039e+000 - endloop - endfacet - facet normal 0.000000e+000 8.715574e-002 9.961947e-001 - outer loop - vertex 4.982020e+001 9.296409e-001 9.924039e+000 - vertex 3.482020e+001 9.296409e-001 9.924039e+000 - vertex 3.482020e+001 6.140000e-002 1.000000e+001 - endloop - endfacet - facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 - outer loop - vertex 4.982020e+001 6.140000e-002 1.000000e+001 - vertex 3.482020e+001 6.140000e-002 1.000000e+001 - vertex 3.482020e+001 -8.068409e-001 9.924039e+000 - endloop - endfacet - facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 - outer loop - vertex 4.982020e+001 -8.068409e-001 9.924039e+000 - vertex 3.482020e+001 -8.068409e-001 9.924039e+000 - vertex 3.482020e+001 -1.648701e+000 9.698463e+000 - endloop - endfacet - facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 - outer loop - vertex 4.982020e+001 -1.648701e+000 9.698463e+000 - vertex 3.482020e+001 -1.648701e+000 9.698463e+000 - vertex 3.482020e+001 -2.438600e+000 9.330127e+000 - endloop - endfacet - facet normal 0.000000e+000 -5.735764e-001 8.191520e-001 - outer loop - vertex 4.982020e+001 -2.438600e+000 9.330127e+000 - vertex 3.482020e+001 -2.438600e+000 9.330127e+000 - vertex 3.482020e+001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 - outer loop - vertex 4.982020e+001 -3.152538e+000 8.830222e+000 - vertex 3.482020e+001 -3.152538e+000 8.830222e+000 - vertex 3.482020e+001 -3.768822e+000 8.213938e+000 - endloop - endfacet - facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 - outer loop - vertex 4.982020e+001 -3.768822e+000 8.213938e+000 - vertex 3.482020e+001 -3.768822e+000 8.213938e+000 - vertex 3.482020e+001 -4.268727e+000 7.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 - outer loop - vertex 4.982020e+001 -4.268727e+000 7.500000e+000 - vertex 3.482020e+001 -4.268727e+000 7.500000e+000 - vertex 3.482020e+001 -4.637063e+000 6.710101e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 - outer loop - vertex 4.982020e+001 -4.637063e+000 6.710101e+000 - vertex 3.482020e+001 -4.637063e+000 6.710101e+000 - vertex 3.482020e+001 -4.862639e+000 5.868241e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.961947e-001 8.715574e-002 - outer loop - vertex 4.982020e+001 -4.862639e+000 5.868241e+000 - vertex 3.482020e+001 -4.862639e+000 5.868241e+000 - vertex 3.482020e+001 -4.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002 - outer loop - vertex 4.982020e+001 -4.938600e+000 5.000000e+000 - vertex 3.482020e+001 -4.938600e+000 5.000000e+000 - vertex 3.482020e+001 -4.862639e+000 4.131759e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 - outer loop - vertex 4.982020e+001 -4.862639e+000 4.131759e+000 - vertex 3.482020e+001 -4.862639e+000 4.131759e+000 - vertex 3.482020e+001 -4.637063e+000 3.289899e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 - outer loop - vertex 4.982020e+001 -4.637063e+000 3.289899e+000 - vertex 3.482020e+001 -4.637063e+000 3.289899e+000 - vertex 3.482020e+001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001 - outer loop - vertex 4.982020e+001 -4.268727e+000 2.500000e+000 - vertex 3.482020e+001 -4.268727e+000 2.500000e+000 - vertex 3.482020e+001 -3.768822e+000 1.786062e+000 - endloop - endfacet - facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 - outer loop - vertex 4.982020e+001 -3.768822e+000 1.786062e+000 - vertex 3.482020e+001 -3.768822e+000 1.786062e+000 - vertex 3.482020e+001 -3.152538e+000 1.169778e+000 - endloop - endfacet - facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001 - outer loop - vertex 4.982020e+001 -3.152538e+000 1.169778e+000 - vertex 3.482020e+001 -3.152538e+000 1.169778e+000 - vertex 3.482020e+001 -2.438600e+000 6.698730e-001 - endloop - endfacet - facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001 - outer loop - vertex 4.982020e+001 -2.438600e+000 6.698730e-001 - vertex 3.482020e+001 -2.438600e+000 6.698730e-001 - vertex 3.482020e+001 -1.648701e+000 3.015369e-001 - endloop - endfacet - facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001 - outer loop - vertex 4.982020e+001 -1.648701e+000 3.015369e-001 - vertex 3.482020e+001 -1.648701e+000 3.015369e-001 - vertex 3.482020e+001 -8.068409e-001 7.596123e-002 - endloop - endfacet - facet normal 0.000000e+000 -8.715574e-002 -9.961947e-001 - outer loop - vertex 4.982020e+001 -8.068409e-001 7.596123e-002 - vertex 3.482020e+001 -8.068409e-001 7.596123e-002 - vertex 3.482020e+001 6.140000e-002 0.000000e+000 - endloop - endfacet - facet normal -5.124559e-017 -8.715574e-002 -9.961947e-001 - outer loop - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.982020e+001 -8.068409e-001 7.596123e-002 - vertex 3.482020e+001 6.140000e-002 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 -2.588190e-001 -9.659258e-001 - outer loop - vertex 4.982020e+001 -8.068409e-001 7.596123e-002 - vertex 4.982020e+001 -1.648701e+000 3.015369e-001 - vertex 3.482020e+001 -8.068409e-001 7.596123e-002 - endloop - endfacet - facet normal 0.000000e+000 -4.226183e-001 -9.063078e-001 - outer loop - vertex 4.982020e+001 -1.648701e+000 3.015369e-001 - vertex 4.982020e+001 -2.438600e+000 6.698730e-001 - vertex 3.482020e+001 -1.648701e+000 3.015369e-001 - endloop - endfacet - facet normal 0.000000e+000 -5.735764e-001 -8.191520e-001 - outer loop - vertex 4.982020e+001 -2.438600e+000 6.698730e-001 - vertex 4.982020e+001 -3.152538e+000 1.169778e+000 - vertex 3.482020e+001 -2.438600e+000 6.698730e-001 - endloop - endfacet - facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 - outer loop - vertex 4.982020e+001 -3.152538e+000 1.169778e+000 - vertex 4.982020e+001 -3.768822e+000 1.786062e+000 - vertex 3.482020e+001 -3.152538e+000 1.169778e+000 - endloop - endfacet - facet normal 0.000000e+000 -8.191520e-001 -5.735764e-001 - outer loop - vertex 4.982020e+001 -3.768822e+000 1.786062e+000 - vertex 4.982020e+001 -4.268727e+000 2.500000e+000 - vertex 3.482020e+001 -3.768822e+000 1.786062e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 - outer loop - vertex 4.982020e+001 -4.268727e+000 2.500000e+000 - vertex 4.982020e+001 -4.637063e+000 3.289899e+000 - vertex 3.482020e+001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 - outer loop - vertex 4.982020e+001 -4.637063e+000 3.289899e+000 - vertex 4.982020e+001 -4.862639e+000 4.131759e+000 - vertex 3.482020e+001 -4.637063e+000 3.289899e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.961947e-001 -8.715574e-002 - outer loop - vertex 4.982020e+001 -4.862639e+000 4.131759e+000 - vertex 4.982020e+001 -4.938600e+000 5.000000e+000 - vertex 3.482020e+001 -4.862639e+000 4.131759e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.961947e-001 8.715574e-002 - outer loop - vertex 4.982020e+001 -4.938600e+000 5.000000e+000 - vertex 4.982020e+001 -4.862639e+000 5.868241e+000 - vertex 3.482020e+001 -4.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 - outer loop - vertex 4.982020e+001 -4.862639e+000 5.868241e+000 - vertex 4.982020e+001 -4.637063e+000 6.710101e+000 - vertex 3.482020e+001 -4.862639e+000 5.868241e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 - outer loop - vertex 4.982020e+001 -4.637063e+000 6.710101e+000 - vertex 4.982020e+001 -4.268727e+000 7.500000e+000 - vertex 3.482020e+001 -4.637063e+000 6.710101e+000 - endloop - endfacet - facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 - outer loop - vertex 4.982020e+001 -4.268727e+000 7.500000e+000 - vertex 4.982020e+001 -3.768822e+000 8.213938e+000 - vertex 3.482020e+001 -4.268727e+000 7.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 - outer loop - vertex 4.982020e+001 -3.768822e+000 8.213938e+000 - vertex 4.982020e+001 -3.152538e+000 8.830222e+000 - vertex 3.482020e+001 -3.768822e+000 8.213938e+000 - endloop - endfacet - facet normal 0.000000e+000 -5.735764e-001 8.191520e-001 - outer loop - vertex 4.982020e+001 -3.152538e+000 8.830222e+000 - vertex 4.982020e+001 -2.438600e+000 9.330127e+000 - vertex 3.482020e+001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 - outer loop - vertex 4.982020e+001 -2.438600e+000 9.330127e+000 - vertex 4.982020e+001 -1.648701e+000 9.698463e+000 - vertex 3.482020e+001 -2.438600e+000 9.330127e+000 - endloop - endfacet - facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 - outer loop - vertex 4.982020e+001 -1.648701e+000 9.698463e+000 - vertex 4.982020e+001 -8.068409e-001 9.924039e+000 - vertex 3.482020e+001 -1.648701e+000 9.698463e+000 - endloop - endfacet - facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 - outer loop - vertex 4.982020e+001 -8.068409e-001 9.924039e+000 - vertex 4.982020e+001 6.140000e-002 1.000000e+001 - vertex 3.482020e+001 -8.068409e-001 9.924039e+000 - endloop - endfacet - facet normal 0.000000e+000 8.715574e-002 9.961947e-001 - outer loop - vertex 4.982020e+001 6.140000e-002 1.000000e+001 - vertex 4.982020e+001 9.296409e-001 9.924039e+000 - vertex 3.482020e+001 6.140000e-002 1.000000e+001 - endloop - endfacet - facet normal 0.000000e+000 2.588190e-001 9.659258e-001 - outer loop - vertex 4.982020e+001 9.296409e-001 9.924039e+000 - vertex 4.982020e+001 1.771501e+000 9.698463e+000 - vertex 3.482020e+001 9.296409e-001 9.924039e+000 - endloop - endfacet - facet normal 0.000000e+000 4.226183e-001 9.063078e-001 - outer loop - vertex 4.982020e+001 1.771501e+000 9.698463e+000 - vertex 4.982020e+001 2.561400e+000 9.330127e+000 - vertex 3.482020e+001 1.771501e+000 9.698463e+000 - endloop - endfacet - facet normal 0.000000e+000 5.735764e-001 8.191520e-001 - outer loop - vertex 4.982020e+001 2.561400e+000 9.330127e+000 - vertex 4.982020e+001 3.275338e+000 8.830222e+000 - vertex 3.482020e+001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal 0.000000e+000 7.071068e-001 7.071068e-001 - outer loop - vertex 4.982020e+001 3.275338e+000 8.830222e+000 - vertex 4.982020e+001 3.891622e+000 8.213938e+000 - vertex 3.482020e+001 3.275338e+000 8.830222e+000 - endloop - endfacet - facet normal 0.000000e+000 8.191520e-001 5.735764e-001 - outer loop - vertex 4.982020e+001 3.891622e+000 8.213938e+000 - vertex 4.982020e+001 4.391527e+000 7.500000e+000 - vertex 3.482020e+001 3.891622e+000 8.213938e+000 - endloop - endfacet - facet normal 0.000000e+000 9.063078e-001 4.226183e-001 - outer loop - vertex 4.982020e+001 4.391527e+000 7.500000e+000 - vertex 4.982020e+001 4.759863e+000 6.710101e+000 - vertex 3.482020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 9.659258e-001 2.588190e-001 - outer loop - vertex 4.982020e+001 4.759863e+000 6.710101e+000 - vertex 4.982020e+001 4.985439e+000 5.868241e+000 - vertex 3.482020e+001 4.759863e+000 6.710101e+000 - endloop - endfacet - facet normal 1.432567e-016 1.253334e-017 -1.000000e+000 - outer loop - vertex 4.428222e+001 1.749552e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.432020e+001 1.706140e+001 -8.881784e-016 - endloop - endfacet - facet normal 1.174024e-016 3.145787e-017 -1.000000e+000 - outer loop - vertex 4.428222e+001 1.749552e+001 -8.881784e-016 - vertex 4.416943e+001 1.791645e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal 9.887861e-017 4.610785e-017 -1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.416943e+001 1.791645e+001 -8.881784e-016 - vertex 4.398526e+001 1.831140e+001 -8.881784e-016 - endloop - endfacet - facet normal 8.409715e-017 5.888546e-017 -1.000000e+000 - outer loop - vertex 4.373531e+001 1.866837e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.398526e+001 1.831140e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.118001e-017 7.118001e-017 -1.000000e+000 - outer loop - vertex 4.373531e+001 1.866837e+001 -8.881784e-016 - vertex 4.342717e+001 1.897651e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal 5.888546e-017 8.409715e-017 -1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.342717e+001 1.897651e+001 -8.881784e-016 - vertex 4.307020e+001 1.922646e+001 -8.881784e-016 - endloop - endfacet - facet normal 4.610785e-017 9.887861e-017 -1.000000e+000 - outer loop - vertex 4.267525e+001 1.941063e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.307020e+001 1.922646e+001 -8.881784e-016 - endloop - endfacet - facet normal 3.145787e-017 1.174024e-016 -1.000000e+000 - outer loop - vertex 4.267525e+001 1.941063e+001 -8.881784e-016 - vertex 4.225432e+001 1.952342e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal 1.253334e-017 1.432567e-016 -1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.225432e+001 1.952342e+001 -8.881784e-016 - vertex 4.182020e+001 1.956140e+001 -8.881784e-016 - endloop - endfacet - facet normal -1.618835e-017 1.850337e-016 -1.000000e+000 - outer loop - vertex 4.138608e+001 1.952342e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.182020e+001 1.956140e+001 -8.881784e-016 - endloop - endfacet - facet normal -7.259975e-017 2.709460e-016 -1.000000e+000 - outer loop - vertex 4.138608e+001 1.952342e+001 -8.881784e-016 - vertex 4.096515e+001 1.941063e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 1.571783e-016 -1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.096515e+001 1.941063e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal -1.383491e-031 1.571783e-016 -1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 4.096515e+001 1.941063e+001 -8.881784e-016 - vertex 8.675250e+000 1.941063e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.259975e-017 2.709460e-016 -1.000000e+000 - outer loop - vertex 8.254320e+000 1.952342e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 8.675250e+000 1.941063e+001 -8.881784e-016 - endloop - endfacet - facet normal 1.618835e-017 1.850337e-016 -1.000000e+000 - outer loop - vertex 8.254320e+000 1.952342e+001 -8.881784e-016 - vertex 7.820200e+000 1.956140e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal -1.253334e-017 1.432567e-016 -1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 7.820200e+000 1.956140e+001 -8.881784e-016 - vertex 7.386080e+000 1.952342e+001 -8.881784e-016 - endloop - endfacet - facet normal -3.145787e-017 1.174024e-016 -1.000000e+000 - outer loop - vertex 6.965150e+000 1.941063e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 7.386080e+000 1.952342e+001 -8.881784e-016 - endloop - endfacet - facet normal -4.610785e-017 9.887861e-017 -1.000000e+000 - outer loop - vertex 6.965150e+000 1.941063e+001 -8.881784e-016 - vertex 6.570200e+000 1.922646e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal -5.888546e-017 8.409715e-017 -1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 6.570200e+000 1.922646e+001 -8.881784e-016 - vertex 6.213231e+000 1.897651e+001 -8.881784e-016 - endloop - endfacet - facet normal -7.118001e-017 7.118001e-017 -1.000000e+000 - outer loop - vertex 5.905089e+000 1.866837e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 6.213231e+000 1.897651e+001 -8.881784e-016 - endloop - endfacet - facet normal -8.409715e-017 5.888546e-017 -1.000000e+000 - outer loop - vertex 5.905089e+000 1.866837e+001 -8.881784e-016 - vertex 5.655136e+000 1.831140e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal -9.887861e-017 4.610785e-017 -1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 5.655136e+000 1.831140e+001 -8.881784e-016 - vertex 5.470968e+000 1.791645e+001 -8.881784e-016 - endloop - endfacet - facet normal -1.174024e-016 3.145787e-017 -1.000000e+000 - outer loop - vertex 5.358181e+000 1.749552e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 5.470968e+000 1.791645e+001 -8.881784e-016 - endloop - endfacet - facet normal -1.432567e-016 1.253334e-017 -1.000000e+000 - outer loop - vertex 5.358181e+000 1.749552e+001 -8.881784e-016 - vertex 5.320200e+000 1.706140e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal -1.850337e-016 -1.618835e-017 -1.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 5.320200e+000 1.706140e+001 -8.881784e-016 - vertex 5.358181e+000 1.662728e+001 -8.881784e-016 - endloop - endfacet - facet normal -2.709460e-016 -7.259975e-017 -1.000000e+000 - outer loop - vertex 5.470968e+000 1.620635e+001 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex 5.358181e+000 1.662728e+001 -8.881784e-016 - endloop - endfacet - facet normal -1.015055e-016 3.552714e-017 -1.000000e+000 - outer loop - vertex 5.470968e+000 1.620635e+001 -8.881784e-016 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 5.470968e+000 1.620635e+001 -8.881784e-016 - vertex 5.655136e+000 1.581140e+001 -8.881784e-016 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex 5.655136e+000 1.581140e+001 -8.881784e-016 - vertex 5.905089e+000 1.545443e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 6.213231e+000 1.514629e+001 -8.881784e-016 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex 5.905089e+000 1.545443e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 6.213231e+000 1.514629e+001 -8.881784e-016 - vertex 6.570200e+000 1.489634e+001 -8.881784e-016 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex 6.570200e+000 1.489634e+001 -8.881784e-016 - vertex 6.965150e+000 1.471217e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 7.386080e+000 1.459938e+001 -8.881784e-016 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex 6.965150e+000 1.471217e+001 -8.881784e-016 - endloop - endfacet - facet normal 6.691135e-017 -3.482212e-017 -1.000000e+000 - outer loop - vertex 7.386080e+000 1.459938e+001 -8.881784e-016 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal -7.350854e-018 -8.402064e-017 -1.000000e+000 - outer loop - vertex 7.386080e+000 1.459938e+001 -8.881784e-016 - vertex 7.820200e+000 1.456140e+001 -8.881784e-016 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal 6.587563e-018 -7.529618e-017 -1.000000e+000 - outer loop - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 7.820200e+000 1.456140e+001 -8.881784e-016 - vertex 8.254320e+000 1.459938e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.134736e-017 4.995796e-017 -1.000000e+000 - outer loop - vertex 2.290509e+001 1.145443e+001 0.000000e+000 - vertex 8.254320e+000 1.459938e+001 -8.881784e-016 - vertex 2.265514e+001 1.181140e+001 0.000000e+000 - endloop - endfacet - facet normal 4.990041e-017 -4.995282e-017 -1.000000e+000 - outer loop - vertex 2.290509e+001 1.145443e+001 0.000000e+000 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 8.254320e+000 1.459938e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 2.290509e+001 1.145443e+001 0.000000e+000 - vertex 2.321323e+001 1.114629e+001 0.000000e+000 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 2.321323e+001 1.114629e+001 0.000000e+000 - vertex 2.357020e+001 1.089634e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 2.396515e+001 1.071217e+001 0.000000e+000 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 2.357020e+001 1.089634e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 2.396515e+001 1.071217e+001 0.000000e+000 - vertex 2.438608e+001 1.059938e+001 0.000000e+000 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 2.438608e+001 1.059938e+001 0.000000e+000 - vertex 2.482020e+001 1.056140e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 2.482020e+001 1.056140e+001 0.000000e+000 - vertex 2.525432e+001 1.059938e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 2.567525e+001 1.071217e+001 0.000000e+000 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 2.525432e+001 1.059938e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 2.567525e+001 1.071217e+001 0.000000e+000 - vertex 2.607020e+001 1.089634e+001 0.000000e+000 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 2.607020e+001 1.089634e+001 0.000000e+000 - vertex 2.642717e+001 1.114629e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 2.673531e+001 1.145443e+001 0.000000e+000 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 2.642717e+001 1.114629e+001 0.000000e+000 - endloop - endfacet - facet normal -4.990041e-017 -4.995282e-017 -1.000000e+000 - outer loop - vertex 2.673531e+001 1.145443e+001 0.000000e+000 - vertex 4.138608e+001 1.459938e+001 -8.881784e-016 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal -7.134736e-017 4.995796e-017 -1.000000e+000 - outer loop - vertex 2.673531e+001 1.145443e+001 0.000000e+000 - vertex 2.698526e+001 1.181140e+001 0.000000e+000 - vertex 4.138608e+001 1.459938e+001 -8.881784e-016 - endloop - endfacet - facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000 - outer loop - vertex 4.138608e+001 1.459938e+001 -8.881784e-016 - vertex 2.698526e+001 1.181140e+001 0.000000e+000 - vertex 4.096515e+001 1.471217e+001 -8.881784e-016 - endloop - endfacet - facet normal -7.033831e-017 3.279929e-017 -1.000000e+000 - outer loop - vertex 4.096515e+001 1.471217e+001 -8.881784e-016 - vertex 2.698526e+001 1.181140e+001 0.000000e+000 - vertex 2.716943e+001 1.220635e+001 0.000000e+000 - endloop - endfacet - facet normal -7.004568e-017 1.876868e-017 -1.000000e+000 - outer loop - vertex 4.057020e+001 1.489634e+001 -8.881784e-016 - vertex 2.716943e+001 1.220635e+001 0.000000e+000 - vertex 2.728222e+001 1.262728e+001 0.000000e+000 - endloop - endfacet - facet normal -6.785445e-017 5.936495e-018 -1.000000e+000 - outer loop - vertex 2.732020e+001 1.306140e+001 0.000000e+000 - vertex 4.057020e+001 1.489634e+001 -8.881784e-016 - vertex 2.728222e+001 1.262728e+001 0.000000e+000 - endloop - endfacet - facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000 - outer loop - vertex 2.732020e+001 1.306140e+001 0.000000e+000 - vertex 4.021323e+001 1.514629e+001 -8.881784e-016 - vertex 4.057020e+001 1.489634e+001 -8.881784e-016 - endloop - endfacet - facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000 - outer loop - vertex 2.732020e+001 1.306140e+001 0.000000e+000 - vertex 2.728222e+001 1.349552e+001 0.000000e+000 - vertex 4.021323e+001 1.514629e+001 -8.881784e-016 - endloop - endfacet - facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000 - outer loop - vertex 4.021323e+001 1.514629e+001 -8.881784e-016 - vertex 2.728222e+001 1.349552e+001 0.000000e+000 - vertex 3.990509e+001 1.545443e+001 -8.881784e-016 - endloop - endfacet - facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000 - outer loop - vertex 3.990509e+001 1.545443e+001 -8.881784e-016 - vertex 2.728222e+001 1.349552e+001 0.000000e+000 - vertex 2.716943e+001 1.391645e+001 0.000000e+000 - endloop - endfacet - facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000 - outer loop - vertex 3.965514e+001 1.581140e+001 -8.881784e-016 - vertex 2.716943e+001 1.391645e+001 0.000000e+000 - vertex 2.698526e+001 1.431140e+001 0.000000e+000 - endloop - endfacet - facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000 - outer loop - vertex 3.947097e+001 1.620635e+001 -8.881784e-016 - vertex 2.698526e+001 1.431140e+001 0.000000e+000 - vertex 2.673531e+001 1.466837e+001 0.000000e+000 - endloop - endfacet - facet normal -6.091015e-017 -6.091015e-017 -1.000000e+000 - outer loop - vertex 3.935818e+001 1.662728e+001 -8.881784e-016 - vertex 2.673531e+001 1.466837e+001 0.000000e+000 - vertex 2.642717e+001 1.497651e+001 0.000000e+000 - endloop - endfacet - facet normal -5.596390e-017 -7.992473e-017 -1.000000e+000 - outer loop - vertex 3.932020e+001 1.706140e+001 -8.881784e-016 - vertex 2.642717e+001 1.497651e+001 0.000000e+000 - vertex 2.607020e+001 1.522646e+001 0.000000e+000 - endloop - endfacet - facet normal -7.004568e-017 1.876868e-017 -1.000000e+000 - outer loop - vertex 3.935818e+001 1.749552e+001 -8.881784e-016 - vertex 2.607020e+001 1.522646e+001 0.000000e+000 - vertex 3.947097e+001 1.791645e+001 -8.881784e-016 - endloop - endfacet - facet normal -6.785445e-017 5.936495e-018 -1.000000e+000 - outer loop - vertex 3.935818e+001 1.749552e+001 -8.881784e-016 - vertex 3.932020e+001 1.706140e+001 -8.881784e-016 - vertex 2.607020e+001 1.522646e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 4.096515e+001 1.941063e+001 -8.881784e-016 - vertex 4.057020e+001 1.922646e+001 -8.881784e-016 - vertex 8.675250e+000 1.941063e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 8.675250e+000 1.941063e+001 -8.881784e-016 - vertex 4.057020e+001 1.922646e+001 -8.881784e-016 - vertex 9.070200e+000 1.922646e+001 -8.881784e-016 - endloop - endfacet - facet normal 3.279817e-031 -2.423364e-016 -1.000000e+000 - outer loop - vertex 9.070200e+000 1.922646e+001 -8.881784e-016 - vertex 4.057020e+001 1.922646e+001 -8.881784e-016 - vertex 2.482020e+001 1.556140e+001 0.000000e+000 - endloop - endfacet - facet normal 1.631843e-017 -1.865205e-016 -1.000000e+000 - outer loop - vertex 9.427169e+000 1.897651e+001 -8.881784e-016 - vertex 2.482020e+001 1.556140e+001 0.000000e+000 - vertex 2.438608e+001 1.552342e+001 0.000000e+000 - endloop - endfacet - facet normal 7.134736e-017 4.995796e-017 -1.000000e+000 - outer loop - vertex 9.735311e+000 1.866837e+001 -8.881784e-016 - vertex 2.438608e+001 1.552342e+001 0.000000e+000 - vertex 9.985264e+000 1.831140e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.719385e-017 7.719385e-017 -1.000000e+000 - outer loop - vertex 9.735311e+000 1.866837e+001 -8.881784e-016 - vertex 9.427169e+000 1.897651e+001 -8.881784e-016 - vertex 2.438608e+001 1.552342e+001 0.000000e+000 - endloop - endfacet - facet normal -8.446175e-017 1.206239e-016 -1.000000e+000 - outer loop - vertex 4.021323e+001 1.897651e+001 -8.881784e-016 - vertex 2.482020e+001 1.556140e+001 0.000000e+000 - vertex 4.057020e+001 1.922646e+001 -8.881784e-016 - endloop - endfacet - facet normal -1.631843e-017 -1.865205e-016 -1.000000e+000 - outer loop - vertex 4.021323e+001 1.897651e+001 -8.881784e-016 - vertex 2.525432e+001 1.552342e+001 0.000000e+000 - vertex 2.482020e+001 1.556140e+001 0.000000e+000 - endloop - endfacet - facet normal -7.719385e-017 7.719385e-017 -1.000000e+000 - outer loop - vertex 4.021323e+001 1.897651e+001 -8.881784e-016 - vertex 3.990509e+001 1.866837e+001 -8.881784e-016 - vertex 2.525432e+001 1.552342e+001 0.000000e+000 - endloop - endfacet - facet normal -7.134736e-017 4.995796e-017 -1.000000e+000 - outer loop - vertex 2.525432e+001 1.552342e+001 0.000000e+000 - vertex 3.990509e+001 1.866837e+001 -8.881784e-016 - vertex 3.965514e+001 1.831140e+001 -8.881784e-016 - endloop - endfacet - facet normal -7.033831e-017 3.279929e-017 -1.000000e+000 - outer loop - vertex 2.567525e+001 1.541063e+001 0.000000e+000 - vertex 3.965514e+001 1.831140e+001 -8.881784e-016 - vertex 3.947097e+001 1.791645e+001 -8.881784e-016 - endloop - endfacet - facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000 - outer loop - vertex 2.607020e+001 1.522646e+001 0.000000e+000 - vertex 2.567525e+001 1.541063e+001 0.000000e+000 - vertex 3.947097e+001 1.791645e+001 -8.881784e-016 - endloop - endfacet - facet normal -6.792726e-017 -5.942865e-018 -1.000000e+000 - outer loop - vertex 3.932020e+001 1.706140e+001 -8.881784e-016 - vertex 3.935818e+001 1.662728e+001 -8.881784e-016 - vertex 2.642717e+001 1.497651e+001 0.000000e+000 - endloop - endfacet - facet normal -6.755360e-017 -1.810093e-017 -1.000000e+000 - outer loop - vertex 3.947097e+001 1.620635e+001 -8.881784e-016 - vertex 2.673531e+001 1.466837e+001 0.000000e+000 - vertex 3.935818e+001 1.662728e+001 -8.881784e-016 - endloop - endfacet - facet normal -6.643400e-017 -3.097868e-017 -1.000000e+000 - outer loop - vertex 3.947097e+001 1.620635e+001 -8.881784e-016 - vertex 3.965514e+001 1.581140e+001 -8.881784e-016 - vertex 2.698526e+001 1.431140e+001 0.000000e+000 - endloop - endfacet - facet normal -6.430222e-017 -4.502490e-017 -1.000000e+000 - outer loop - vertex 3.965514e+001 1.581140e+001 -8.881784e-016 - vertex 3.990509e+001 1.545443e+001 -8.881784e-016 - vertex 2.716943e+001 1.391645e+001 0.000000e+000 - endloop - endfacet - facet normal -4.633298e-017 -9.936140e-017 -1.000000e+000 - outer loop - vertex 4.096515e+001 1.471217e+001 -8.881784e-016 - vertex 2.716943e+001 1.220635e+001 0.000000e+000 - vertex 4.057020e+001 1.489634e+001 -8.881784e-016 - endloop - endfacet - facet normal -6.587563e-018 -7.529618e-017 -1.000000e+000 - outer loop - vertex 4.182020e+001 1.456140e+001 -8.881784e-016 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 4.138608e+001 1.459938e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.350854e-018 -8.402064e-017 -1.000000e+000 - outer loop - vertex 4.182020e+001 1.456140e+001 -8.881784e-016 - vertex 4.225432e+001 1.459938e+001 -8.881784e-016 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - endloop - endfacet - facet normal -6.691135e-017 -3.482212e-017 -1.000000e+000 - outer loop - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 4.225432e+001 1.459938e+001 -8.881784e-016 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal -5.921189e-017 0.000000e+000 -1.000000e+000 - outer loop - vertex 3.482020e+001 6.140000e-002 0.000000e+000 - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 4.267525e+001 1.471217e+001 -8.881784e-016 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.225432e+001 1.459938e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 4.267525e+001 1.471217e+001 -8.881784e-016 - vertex 4.307020e+001 1.489634e+001 -8.881784e-016 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.307020e+001 1.489634e+001 -8.881784e-016 - vertex 4.342717e+001 1.514629e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 4.373531e+001 1.545443e+001 -8.881784e-016 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.342717e+001 1.514629e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 4.373531e+001 1.545443e+001 -8.881784e-016 - vertex 4.398526e+001 1.581140e+001 -8.881784e-016 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.398526e+001 1.581140e+001 -8.881784e-016 - vertex 4.416943e+001 1.620635e+001 -8.881784e-016 - endloop - endfacet - facet normal 2.709460e-016 -7.259975e-017 -1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.416943e+001 1.620635e+001 -8.881784e-016 - vertex 4.428222e+001 1.662728e+001 -8.881784e-016 - endloop - endfacet - facet normal 1.850337e-016 -1.618835e-017 -1.000000e+000 - outer loop - vertex 4.432020e+001 1.706140e+001 -8.881784e-016 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.428222e+001 1.662728e+001 -8.881784e-016 - endloop - endfacet - facet normal -3.580541e-017 -1.336276e-016 -1.000000e+000 - outer loop - vertex 2.567525e+001 1.541063e+001 0.000000e+000 - vertex 2.525432e+001 1.552342e+001 0.000000e+000 - vertex 3.965514e+001 1.831140e+001 -8.881784e-016 - endloop - endfacet - facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000 - outer loop - vertex 2.438608e+001 1.552342e+001 0.000000e+000 - vertex 2.396515e+001 1.541063e+001 0.000000e+000 - vertex 9.985264e+000 1.831140e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.033831e-017 3.279929e-017 -1.000000e+000 - outer loop - vertex 9.985264e+000 1.831140e+001 -8.881784e-016 - vertex 2.396515e+001 1.541063e+001 0.000000e+000 - vertex 1.016943e+001 1.791645e+001 -8.881784e-016 - endloop - endfacet - facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000 - outer loop - vertex 1.016943e+001 1.791645e+001 -8.881784e-016 - vertex 2.396515e+001 1.541063e+001 0.000000e+000 - vertex 2.357020e+001 1.522646e+001 0.000000e+000 - endloop - endfacet - facet normal 6.785445e-017 5.936495e-018 -1.000000e+000 - outer loop - vertex 1.028222e+001 1.749552e+001 -8.881784e-016 - vertex 2.357020e+001 1.522646e+001 0.000000e+000 - vertex 1.032020e+001 1.706140e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.004568e-017 1.876868e-017 -1.000000e+000 - outer loop - vertex 1.028222e+001 1.749552e+001 -8.881784e-016 - vertex 1.016943e+001 1.791645e+001 -8.881784e-016 - vertex 2.357020e+001 1.522646e+001 0.000000e+000 - endloop - endfacet - facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000 - outer loop - vertex 2.357020e+001 1.522646e+001 0.000000e+000 - vertex 2.321323e+001 1.497651e+001 0.000000e+000 - vertex 1.032020e+001 1.706140e+001 -8.881784e-016 - endloop - endfacet - facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000 - outer loop - vertex 1.032020e+001 1.706140e+001 -8.881784e-016 - vertex 2.321323e+001 1.497651e+001 0.000000e+000 - vertex 1.028222e+001 1.662728e+001 -8.881784e-016 - endloop - endfacet - facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000 - outer loop - vertex 1.028222e+001 1.662728e+001 -8.881784e-016 - vertex 2.321323e+001 1.497651e+001 0.000000e+000 - vertex 2.290509e+001 1.466837e+001 0.000000e+000 - endloop - endfacet - facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000 - outer loop - vertex 1.016943e+001 1.620635e+001 -8.881784e-016 - vertex 2.290509e+001 1.466837e+001 0.000000e+000 - vertex 2.265514e+001 1.431140e+001 0.000000e+000 - endloop - endfacet - facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000 - outer loop - vertex 9.985264e+000 1.581140e+001 -8.881784e-016 - vertex 2.265514e+001 1.431140e+001 0.000000e+000 - vertex 2.247097e+001 1.391645e+001 0.000000e+000 - endloop - endfacet - facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000 - outer loop - vertex 9.735311e+000 1.545443e+001 -8.881784e-016 - vertex 2.247097e+001 1.391645e+001 0.000000e+000 - vertex 2.235818e+001 1.349552e+001 0.000000e+000 - endloop - endfacet - facet normal 6.792726e-017 -5.942865e-018 -1.000000e+000 - outer loop - vertex 9.427169e+000 1.514629e+001 -8.881784e-016 - vertex 2.235818e+001 1.349552e+001 0.000000e+000 - vertex 2.232020e+001 1.306140e+001 0.000000e+000 - endloop - endfacet - facet normal 6.785445e-017 5.936495e-018 -1.000000e+000 - outer loop - vertex 9.070200e+000 1.489634e+001 -8.881784e-016 - vertex 2.232020e+001 1.306140e+001 0.000000e+000 - vertex 2.235818e+001 1.262728e+001 0.000000e+000 - endloop - endfacet - facet normal 7.004568e-017 1.876868e-017 -1.000000e+000 - outer loop - vertex 2.247097e+001 1.220635e+001 0.000000e+000 - vertex 9.070200e+000 1.489634e+001 -8.881784e-016 - vertex 2.235818e+001 1.262728e+001 0.000000e+000 - endloop - endfacet - facet normal 4.633298e-017 -9.936140e-017 -1.000000e+000 - outer loop - vertex 2.247097e+001 1.220635e+001 0.000000e+000 - vertex 8.675250e+000 1.471217e+001 -8.881784e-016 - vertex 9.070200e+000 1.489634e+001 -8.881784e-016 - endloop - endfacet - facet normal 7.033831e-017 3.279929e-017 -1.000000e+000 - outer loop - vertex 2.247097e+001 1.220635e+001 0.000000e+000 - vertex 2.265514e+001 1.181140e+001 0.000000e+000 - vertex 8.675250e+000 1.471217e+001 -8.881784e-016 - endloop - endfacet - facet normal 3.580541e-017 -1.336276e-016 -1.000000e+000 - outer loop - vertex 8.675250e+000 1.471217e+001 -8.881784e-016 - vertex 2.265514e+001 1.181140e+001 0.000000e+000 - vertex 8.254320e+000 1.459938e+001 -8.881784e-016 - endloop - endfacet - facet normal 8.446175e-017 1.206239e-016 -1.000000e+000 - outer loop - vertex 9.427169e+000 1.897651e+001 -8.881784e-016 - vertex 9.070200e+000 1.922646e+001 -8.881784e-016 - vertex 2.482020e+001 1.556140e+001 0.000000e+000 - endloop - endfacet - facet normal 5.596390e-017 -7.992473e-017 -1.000000e+000 - outer loop - vertex 9.427169e+000 1.514629e+001 -8.881784e-016 - vertex 2.232020e+001 1.306140e+001 0.000000e+000 - vertex 9.070200e+000 1.489634e+001 -8.881784e-016 - endloop - endfacet - facet normal 6.091015e-017 -6.091015e-017 -1.000000e+000 - outer loop - vertex 9.427169e+000 1.514629e+001 -8.881784e-016 - vertex 9.735311e+000 1.545443e+001 -8.881784e-016 - vertex 2.235818e+001 1.349552e+001 0.000000e+000 - endloop - endfacet - facet normal 6.430222e-017 -4.502490e-017 -1.000000e+000 - outer loop - vertex 9.985264e+000 1.581140e+001 -8.881784e-016 - vertex 2.247097e+001 1.391645e+001 0.000000e+000 - vertex 9.735311e+000 1.545443e+001 -8.881784e-016 - endloop - endfacet - facet normal 6.643400e-017 -3.097868e-017 -1.000000e+000 - outer loop - vertex 9.985264e+000 1.581140e+001 -8.881784e-016 - vertex 1.016943e+001 1.620635e+001 -8.881784e-016 - vertex 2.265514e+001 1.431140e+001 0.000000e+000 - endloop - endfacet - facet normal 6.755360e-017 -1.810093e-017 -1.000000e+000 - outer loop - vertex 1.028222e+001 1.662728e+001 -8.881784e-016 - vertex 2.290509e+001 1.466837e+001 0.000000e+000 - vertex 1.016943e+001 1.620635e+001 -8.881784e-016 - endloop - endfacet - facet normal 5.921189e-017 0.000000e+000 -1.000000e+000 - outer loop - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 1.482020e+001 6.140000e-002 0.000000e+000 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 1.015055e-016 3.552714e-017 -1.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.416943e+001 1.620635e+001 -8.881784e-016 - endloop - endfacet - facet normal 0.000000e+000 0.000000e+000 -1.000000e+000 - outer loop - vertex 3.482020e+001 3.378025e+000 0.000000e+000 - vertex 1.482020e+001 3.378025e+000 0.000000e+000 - vertex 2.482020e+001 1.056140e+001 0.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 1.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - endloop - endfacet - facet normal 0.000000e+000 1.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.938600e+000 5.000000e+000 - vertex -1.798000e-001 -2.893023e+000 4.479055e+000 - vertex -1.798000e-001 -4.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -4.862639e+000 5.868241e+000 - vertex -1.798000e-001 -2.938600e+000 5.000000e+000 - vertex -1.798000e-001 -4.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -4.862639e+000 5.868241e+000 - vertex -1.798000e-001 -2.893023e+000 5.520945e+000 - vertex -1.798000e-001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -4.862639e+000 5.868241e+000 - vertex -1.798000e-001 -4.637063e+000 6.710101e+000 - vertex -1.798000e-001 -2.893023e+000 5.520945e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.893023e+000 5.520945e+000 - vertex -1.798000e-001 -4.637063e+000 6.710101e+000 - vertex -1.798000e-001 -2.757678e+000 6.026060e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.757678e+000 6.026060e+000 - vertex -1.798000e-001 -4.637063e+000 6.710101e+000 - vertex -1.798000e-001 -4.268727e+000 7.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.536676e+000 6.500000e+000 - vertex -1.798000e-001 -4.268727e+000 7.500000e+000 - vertex -1.798000e-001 -3.768822e+000 8.213938e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.236733e+000 6.928363e+000 - vertex -1.798000e-001 -3.768822e+000 8.213938e+000 - vertex -1.798000e-001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -1.866963e+000 7.298133e+000 - vertex -1.798000e-001 -3.152538e+000 8.830222e+000 - vertex -1.798000e-001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -1.866963e+000 7.298133e+000 - vertex -1.798000e-001 -2.236733e+000 6.928363e+000 - vertex -1.798000e-001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.893023e+000 4.479055e+000 - vertex -1.798000e-001 -2.757678e+000 3.973940e+000 - vertex -1.798000e-001 -4.862639e+000 4.131759e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -4.938600e+000 5.000000e+000 - vertex -1.798000e-001 -2.893023e+000 4.479055e+000 - vertex -1.798000e-001 -4.862639e+000 4.131759e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.536676e+000 3.500000e+000 - vertex -1.798000e-001 -4.637063e+000 3.289899e+000 - vertex -1.798000e-001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.536676e+000 3.500000e+000 - vertex -1.798000e-001 -4.268727e+000 2.500000e+000 - vertex -1.798000e-001 -4.637063e+000 3.289899e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.536676e+000 3.500000e+000 - vertex -1.798000e-001 -2.236733e+000 3.071637e+000 - vertex -1.798000e-001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -4.268727e+000 2.500000e+000 - vertex -1.798000e-001 -2.236733e+000 3.071637e+000 - vertex -1.798000e-001 -3.768822e+000 1.786062e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -3.768822e+000 1.786062e+000 - vertex -1.798000e-001 -2.236733e+000 3.071637e+000 - vertex -1.798000e-001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -3.152538e+000 1.169778e+000 - vertex -1.798000e-001 -1.866963e+000 2.701867e+000 - vertex -1.798000e-001 -2.438600e+000 6.698730e-001 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -3.152538e+000 1.169778e+000 - vertex -1.798000e-001 -3.768822e+000 1.786062e+000 - vertex -1.798000e-001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -1.438600e+000 2.401924e+000 - vertex -1.798000e-001 -2.438600e+000 6.698730e-001 - vertex -1.798000e-001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -1.438600e+000 2.401924e+000 - vertex -1.798000e-001 -1.648701e+000 3.015369e-001 - vertex -1.798000e-001 -2.438600e+000 6.698730e-001 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -1.438600e+000 2.401924e+000 - vertex -1.798000e-001 -9.646604e-001 2.180922e+000 - vertex -1.798000e-001 -1.648701e+000 3.015369e-001 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -1.648701e+000 3.015369e-001 - vertex -1.798000e-001 -9.646604e-001 2.180922e+000 - vertex -1.798000e-001 -8.068409e-001 7.596123e-002 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -8.068409e-001 7.596123e-002 - vertex -1.798000e-001 -9.646604e-001 2.180922e+000 - vertex -1.798000e-001 -4.595445e-001 2.045577e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex -1.798000e-001 -4.595445e-001 2.045577e+000 - vertex -1.798000e-001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 5.823445e-001 2.045577e+000 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex -1.798000e-001 6.140000e-002 2.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 5.823445e-001 2.045577e+000 - vertex -1.798000e-001 1.087460e+000 2.180922e+000 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex -1.798000e-001 1.087460e+000 2.180922e+000 - vertex -1.798000e-001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 1.989763e+000 2.701867e+000 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex -1.798000e-001 1.561400e+000 2.401924e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 1.989763e+000 2.701867e+000 - vertex -1.798000e-001 2.359533e+000 3.071637e+000 - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex -1.798000e-001 2.359533e+000 3.071637e+000 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 -2.095500e-016 -1.548743e-015 - outer loop - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex -1.798000e-001 2.359533e+000 3.071637e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 1.776357e-016 0.000000e+000 - outer loop - vertex -1.798000e-001 2.506140e+001 5.000000e+000 - vertex -1.798000e-001 2.506140e+001 0.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 -2.628500e-015 1.840496e-015 - outer loop - vertex -1.798000e-001 2.359533e+000 3.071637e+000 - vertex -1.798000e-001 2.659476e+000 3.500000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 -2.086809e-015 9.730950e-016 - outer loop - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex -1.798000e-001 2.659476e+000 3.500000e+000 - vertex -1.798000e-001 2.880478e+000 3.973940e+000 - endloop - endfacet - facet normal -1.000000e+000 -1.863973e-015 4.994500e-016 - outer loop - vertex -1.798000e-001 3.015823e+000 4.479055e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex -1.798000e-001 2.880478e+000 3.973940e+000 - endloop - endfacet - facet normal -1.000000e+000 -1.776357e-015 1.554111e-016 - outer loop - vertex -1.798000e-001 3.015823e+000 4.479055e+000 - vertex -1.798000e-001 3.061400e+000 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 -1.776357e-015 -1.554111e-016 - outer loop - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex -1.798000e-001 3.061400e+000 5.000000e+000 - vertex -1.798000e-001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 4.985439e+000 5.868241e+000 - vertex -1.798000e-001 3.015823e+000 5.520945e+000 - vertex -1.798000e-001 2.880478e+000 6.026060e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 4.759863e+000 6.710101e+000 - vertex -1.798000e-001 2.880478e+000 6.026060e+000 - vertex -1.798000e-001 2.659476e+000 6.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 4.391527e+000 7.500000e+000 - vertex -1.798000e-001 2.659476e+000 6.500000e+000 - vertex -1.798000e-001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 3.891622e+000 8.213938e+000 - vertex -1.798000e-001 2.359533e+000 6.928363e+000 - vertex -1.798000e-001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 3.275338e+000 8.830222e+000 - vertex -1.798000e-001 1.989763e+000 7.298133e+000 - vertex -1.798000e-001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 3.275338e+000 8.830222e+000 - vertex -1.798000e-001 3.891622e+000 8.213938e+000 - vertex -1.798000e-001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 1.989763e+000 7.298133e+000 - vertex -1.798000e-001 1.561400e+000 7.598076e+000 - vertex -1.798000e-001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 2.561400e+000 9.330127e+000 - vertex -1.798000e-001 1.561400e+000 7.598076e+000 - vertex -1.798000e-001 1.771501e+000 9.698463e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 1.771501e+000 9.698463e+000 - vertex -1.798000e-001 1.561400e+000 7.598076e+000 - vertex -1.798000e-001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 9.296409e-001 9.924039e+000 - vertex -1.798000e-001 1.087460e+000 7.819078e+000 - vertex -1.798000e-001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 1.000000e+001 - vertex -1.798000e-001 5.823445e-001 7.954423e+000 - vertex -1.798000e-001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -8.068409e-001 9.924039e+000 - vertex -1.798000e-001 6.140000e-002 8.000000e+000 - vertex -1.798000e-001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -1.648701e+000 9.698463e+000 - vertex -1.798000e-001 -4.595445e-001 7.954423e+000 - vertex -1.798000e-001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.438600e+000 9.330127e+000 - vertex -1.798000e-001 -9.646604e-001 7.819078e+000 - vertex -1.798000e-001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -3.152538e+000 8.830222e+000 - vertex -1.798000e-001 -2.438600e+000 9.330127e+000 - vertex -1.798000e-001 -1.438600e+000 7.598076e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.536676e+000 6.500000e+000 - vertex -1.798000e-001 -3.768822e+000 8.213938e+000 - vertex -1.798000e-001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -4.268727e+000 7.500000e+000 - vertex -1.798000e-001 -2.536676e+000 6.500000e+000 - vertex -1.798000e-001 -2.757678e+000 6.026060e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex -1.798000e-001 -8.068409e-001 7.596123e-002 - vertex -1.798000e-001 -4.595445e-001 2.045577e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -4.637063e+000 3.289899e+000 - vertex -1.798000e-001 -4.862639e+000 4.131759e+000 - vertex -1.798000e-001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -2.438600e+000 9.330127e+000 - vertex -1.798000e-001 -1.648701e+000 9.698463e+000 - vertex -1.798000e-001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 -1.648701e+000 9.698463e+000 - vertex -1.798000e-001 -8.068409e-001 9.924039e+000 - vertex -1.798000e-001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 1.000000e+001 - vertex -1.798000e-001 6.140000e-002 8.000000e+000 - vertex -1.798000e-001 -8.068409e-001 9.924039e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 6.140000e-002 1.000000e+001 - vertex -1.798000e-001 9.296409e-001 9.924039e+000 - vertex -1.798000e-001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 9.296409e-001 9.924039e+000 - vertex -1.798000e-001 1.771501e+000 9.698463e+000 - vertex -1.798000e-001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 2.359533e+000 6.928363e+000 - vertex -1.798000e-001 3.891622e+000 8.213938e+000 - vertex -1.798000e-001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 4.391527e+000 7.500000e+000 - vertex -1.798000e-001 4.759863e+000 6.710101e+000 - vertex -1.798000e-001 2.659476e+000 6.500000e+000 - endloop - endfacet - facet normal -1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex -1.798000e-001 4.759863e+000 6.710101e+000 - vertex -1.798000e-001 4.985439e+000 5.868241e+000 - vertex -1.798000e-001 2.880478e+000 6.026060e+000 - endloop - endfacet - facet normal -1.000000e+000 -7.105427e-016 4.029688e-015 - outer loop - vertex -1.798000e-001 4.985439e+000 5.868241e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex -1.798000e-001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal -1.061532e-017 -8.715574e-002 -9.961947e-001 - outer loop - vertex 1.482020e+001 6.140000e-002 0.000000e+000 - vertex 1.482020e+001 -8.068409e-001 7.596123e-002 - vertex -1.798000e-001 -8.068409e-001 7.596123e-002 - endloop - endfacet - facet normal 5.124559e-017 -8.715574e-002 -9.961947e-001 - outer loop - vertex -1.798000e-001 6.140000e-002 -8.881784e-016 - vertex 1.482020e+001 6.140000e-002 0.000000e+000 - vertex -1.798000e-001 -8.068409e-001 7.596123e-002 - endloop - endfacet - facet normal 2.547676e-017 -2.588190e-001 -9.659258e-001 - outer loop - vertex 1.482020e+001 -8.068409e-001 7.596123e-002 - vertex 1.482020e+001 -1.648701e+000 3.015369e-001 - vertex -1.798000e-001 -1.648701e+000 3.015369e-001 - endloop - endfacet - facet normal -3.065033e-017 -2.588190e-001 -9.659258e-001 - outer loop - vertex -1.798000e-001 -8.068409e-001 7.596123e-002 - vertex 1.482020e+001 -8.068409e-001 7.596123e-002 - vertex -1.798000e-001 -1.648701e+000 3.015369e-001 - endloop - endfacet - facet normal 4.246127e-018 -4.226183e-001 -9.063078e-001 - outer loop - vertex 1.482020e+001 -1.648701e+000 3.015369e-001 - vertex 1.482020e+001 -2.438600e+000 6.698730e-001 - vertex -1.798000e-001 -2.438600e+000 6.698730e-001 - endloop - endfacet - facet normal 3.616145e-018 -4.226183e-001 -9.063078e-001 - outer loop - vertex -1.798000e-001 -1.648701e+000 3.015369e-001 - vertex 1.482020e+001 -1.648701e+000 3.015369e-001 - vertex -1.798000e-001 -2.438600e+000 6.698730e-001 - endloop - endfacet - facet normal 8.492254e-018 -5.735764e-001 -8.191520e-001 - outer loop - vertex 1.482020e+001 -2.438600e+000 6.698730e-001 - vertex 1.482020e+001 -3.152538e+000 1.169778e+000 - vertex -1.798000e-001 -3.152538e+000 1.169778e+000 - endloop - endfacet - facet normal -2.427694e-017 -5.735764e-001 -8.191520e-001 - outer loop - vertex -1.798000e-001 -2.438600e+000 6.698730e-001 - vertex 1.482020e+001 -2.438600e+000 6.698730e-001 - vertex -1.798000e-001 -3.152538e+000 1.169778e+000 - endloop - endfacet - facet normal 0.000000e+000 -7.071068e-001 -7.071068e-001 - outer loop - vertex 1.482020e+001 -3.152538e+000 1.169778e+000 - vertex 1.482020e+001 -3.768822e+000 1.786062e+000 - vertex -1.798000e-001 -3.768822e+000 1.786062e+000 - endloop - endfacet - facet normal -4.186913e-017 -7.071068e-001 -7.071068e-001 - outer loop - vertex -1.798000e-001 -3.152538e+000 1.169778e+000 - vertex 1.482020e+001 -3.152538e+000 1.169778e+000 - vertex -1.798000e-001 -3.768822e+000 1.786062e+000 - endloop - endfacet - facet normal 2.123063e-017 -8.191520e-001 -5.735764e-001 - outer loop - vertex 1.482020e+001 -3.768822e+000 1.786062e+000 - vertex 1.482020e+001 -4.268727e+000 2.500000e+000 - vertex -1.798000e-001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal -2.908199e-017 -8.191520e-001 -5.735764e-001 - outer loop - vertex -1.798000e-001 -3.768822e+000 1.786062e+000 - vertex 1.482020e+001 -3.768822e+000 1.786062e+000 - vertex -1.798000e-001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal -3.616145e-018 -9.063078e-001 -4.226183e-001 - outer loop - vertex 1.482020e+001 -4.268727e+000 2.500000e+000 - vertex 1.482020e+001 -4.637063e+000 3.289899e+000 - vertex -1.798000e-001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.063078e-001 -4.226183e-001 - outer loop - vertex -1.798000e-001 -4.268727e+000 2.500000e+000 - vertex 1.482020e+001 -4.637063e+000 3.289899e+000 - vertex -1.798000e-001 -4.637063e+000 3.289899e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.659258e-001 -2.588190e-001 - outer loop - vertex -1.798000e-001 -4.637063e+000 3.289899e+000 - vertex 1.482020e+001 -4.637063e+000 3.289899e+000 - vertex -1.798000e-001 -4.862639e+000 4.131759e+000 - endloop - endfacet - facet normal 6.130066e-017 -9.659258e-001 -2.588190e-001 - outer loop - vertex -1.798000e-001 -4.862639e+000 4.131759e+000 - vertex 1.482020e+001 -4.637063e+000 3.289899e+000 - vertex 1.482020e+001 -4.862639e+000 4.131759e+000 - endloop - endfacet - facet normal -2.802264e-017 -9.961947e-001 -8.715574e-002 - outer loop - vertex -1.798000e-001 -4.938600e+000 5.000000e+000 - vertex 1.482020e+001 -4.862639e+000 4.131759e+000 - vertex 1.482020e+001 -4.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 3.318329e-017 -9.961947e-001 8.715574e-002 - outer loop - vertex -1.798000e-001 -4.862639e+000 5.868241e+000 - vertex 1.482020e+001 -4.938600e+000 5.000000e+000 - vertex 1.482020e+001 -4.862639e+000 5.868241e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.659258e-001 2.588190e-001 - outer loop - vertex -1.798000e-001 -4.637063e+000 6.710101e+000 - vertex 1.482020e+001 -4.862639e+000 5.868241e+000 - vertex 1.482020e+001 -4.637063e+000 6.710101e+000 - endloop - endfacet - facet normal 7.232290e-018 -9.063078e-001 4.226183e-001 - outer loop - vertex -1.798000e-001 -4.268727e+000 7.500000e+000 - vertex 1.482020e+001 -4.637063e+000 6.710101e+000 - vertex 1.482020e+001 -4.268727e+000 7.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 -8.191520e-001 5.735764e-001 - outer loop - vertex -1.798000e-001 -3.768822e+000 8.213938e+000 - vertex 1.482020e+001 -4.268727e+000 7.500000e+000 - vertex 1.482020e+001 -3.768822e+000 8.213938e+000 - endloop - endfacet - facet normal -2.172279e-030 -7.071068e-001 7.071068e-001 - outer loop - vertex -1.798000e-001 -3.152538e+000 8.830222e+000 - vertex 1.482020e+001 -3.768822e+000 8.213938e+000 - vertex 1.482020e+001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal 3.884310e-017 -5.735764e-001 8.191520e-001 - outer loop - vertex -1.798000e-001 -2.438600e+000 9.330127e+000 - vertex 1.482020e+001 -3.152538e+000 8.830222e+000 - vertex 1.482020e+001 -2.438600e+000 9.330127e+000 - endloop - endfacet - facet normal 0.000000e+000 -4.226183e-001 9.063078e-001 - outer loop - vertex -1.798000e-001 -1.648701e+000 9.698463e+000 - vertex 1.482020e+001 -2.438600e+000 9.330127e+000 - vertex 1.482020e+001 -1.648701e+000 9.698463e+000 - endloop - endfacet - facet normal 8.428841e-017 -2.588190e-001 9.659258e-001 - outer loop - vertex -1.798000e-001 -8.068409e-001 9.924039e+000 - vertex 1.482020e+001 -1.648701e+000 9.698463e+000 - vertex 1.482020e+001 -8.068409e-001 9.924039e+000 - endloop - endfacet - facet normal 0.000000e+000 -8.715574e-002 9.961947e-001 - outer loop - vertex -1.798000e-001 6.140000e-002 1.000000e+001 - vertex 1.482020e+001 -8.068409e-001 9.924039e+000 - vertex 1.482020e+001 6.140000e-002 1.000000e+001 - endloop - endfacet - facet normal -2.322295e-017 8.715574e-002 9.961947e-001 - outer loop - vertex -1.798000e-001 9.296409e-001 9.924039e+000 - vertex 1.482020e+001 6.140000e-002 1.000000e+001 - vertex 1.482020e+001 9.296409e-001 9.924039e+000 - endloop - endfacet - facet normal 4.159406e-017 2.588190e-001 9.659258e-001 - outer loop - vertex -1.798000e-001 1.771501e+000 9.698463e+000 - vertex 1.482020e+001 9.296409e-001 9.924039e+000 - vertex 1.482020e+001 1.771501e+000 9.698463e+000 - endloop - endfacet - facet normal 0.000000e+000 4.226183e-001 9.063078e-001 - outer loop - vertex -1.798000e-001 2.561400e+000 9.330127e+000 - vertex 1.482020e+001 1.771501e+000 9.698463e+000 - vertex 1.482020e+001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal 5.816399e-017 5.735764e-001 8.191520e-001 - outer loop - vertex -1.798000e-001 3.275338e+000 8.830222e+000 - vertex 1.482020e+001 2.561400e+000 9.330127e+000 - vertex 1.482020e+001 3.275338e+000 8.830222e+000 - endloop - endfacet - facet normal 0.000000e+000 7.071068e-001 7.071068e-001 - outer loop - vertex -1.798000e-001 3.891622e+000 8.213938e+000 - vertex 1.482020e+001 3.275338e+000 8.830222e+000 - vertex 1.482020e+001 3.891622e+000 8.213938e+000 - endloop - endfacet - facet normal 3.884310e-017 8.191520e-001 5.735764e-001 - outer loop - vertex -1.798000e-001 4.391527e+000 7.500000e+000 - vertex 1.482020e+001 3.891622e+000 8.213938e+000 - vertex 1.482020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 7.145594e-017 9.063078e-001 4.226183e-001 - outer loop - vertex -1.798000e-001 4.759863e+000 6.710101e+000 - vertex 1.482020e+001 4.391527e+000 7.500000e+000 - vertex 1.482020e+001 4.759863e+000 6.710101e+000 - endloop - endfacet - facet normal 0.000000e+000 9.659258e-001 2.588190e-001 - outer loop - vertex -1.798000e-001 4.985439e+000 5.868241e+000 - vertex 1.482020e+001 4.759863e+000 6.710101e+000 - vertex 1.482020e+001 4.985439e+000 5.868241e+000 - endloop - endfacet - facet normal 0.000000e+000 9.961947e-001 8.715574e-002 - outer loop - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - vertex -1.798000e-001 4.985439e+000 5.868241e+000 - vertex 1.482020e+001 4.985439e+000 5.868241e+000 - endloop - endfacet - facet normal 0.000000e+000 9.961947e-001 8.715574e-002 - outer loop - vertex 1.482020e+001 5.061400e+000 5.000000e+000 - vertex -1.798000e-001 5.061400e+000 5.000000e+000 - vertex -1.798000e-001 4.985439e+000 5.868241e+000 - endloop - endfacet - facet normal 1.910757e-017 9.659258e-001 2.588190e-001 - outer loop - vertex -1.798000e-001 4.985439e+000 5.868241e+000 - vertex -1.798000e-001 4.759863e+000 6.710101e+000 - vertex 1.482020e+001 4.759863e+000 6.710101e+000 - endloop - endfacet - facet normal -8.492254e-018 9.063078e-001 4.226183e-001 - outer loop - vertex -1.798000e-001 4.759863e+000 6.710101e+000 - vertex -1.798000e-001 4.391527e+000 7.500000e+000 - vertex 1.482020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 8.191520e-001 5.735764e-001 - outer loop - vertex -1.798000e-001 4.391527e+000 7.500000e+000 - vertex -1.798000e-001 3.891622e+000 8.213938e+000 - vertex 1.482020e+001 3.891622e+000 8.213938e+000 - endloop - endfacet - facet normal -4.344559e-030 7.071068e-001 7.071068e-001 - outer loop - vertex -1.798000e-001 3.275338e+000 8.830222e+000 - vertex 1.482020e+001 3.275338e+000 8.830222e+000 - vertex -1.798000e-001 3.891622e+000 8.213938e+000 - endloop - endfacet - facet normal 0.000000e+000 5.735764e-001 8.191520e-001 - outer loop - vertex -1.798000e-001 3.275338e+000 8.830222e+000 - vertex -1.798000e-001 2.561400e+000 9.330127e+000 - vertex 1.482020e+001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal -1.153573e-017 4.226183e-001 9.063078e-001 - outer loop - vertex -1.798000e-001 1.771501e+000 9.698463e+000 - vertex 1.482020e+001 1.771501e+000 9.698463e+000 - vertex -1.798000e-001 2.561400e+000 9.330127e+000 - endloop - endfacet - facet normal -6.793803e-017 2.588190e-001 9.659258e-001 - outer loop - vertex -1.798000e-001 1.771501e+000 9.698463e+000 - vertex -1.798000e-001 9.296409e-001 9.924039e+000 - vertex 1.482020e+001 9.296409e-001 9.924039e+000 - endloop - endfacet - facet normal 0.000000e+000 8.715574e-002 9.961947e-001 - outer loop - vertex -1.798000e-001 9.296409e-001 9.924039e+000 - vertex -1.798000e-001 6.140000e-002 1.000000e+001 - vertex 1.482020e+001 6.140000e-002 1.000000e+001 - endloop - endfacet - facet normal 2.866136e-017 -8.715574e-002 9.961947e-001 - outer loop - vertex -1.798000e-001 6.140000e-002 1.000000e+001 - vertex -1.798000e-001 -8.068409e-001 9.924039e+000 - vertex 1.482020e+001 -8.068409e-001 9.924039e+000 - endloop - endfacet - facet normal 0.000000e+000 -2.588190e-001 9.659258e-001 - outer loop - vertex -1.798000e-001 -8.068409e-001 9.924039e+000 - vertex -1.798000e-001 -1.648701e+000 9.698463e+000 - vertex 1.482020e+001 -1.648701e+000 9.698463e+000 - endloop - endfacet - facet normal -8.492254e-018 -4.226183e-001 9.063078e-001 - outer loop - vertex -1.798000e-001 -1.648701e+000 9.698463e+000 - vertex -1.798000e-001 -2.438600e+000 9.330127e+000 - vertex 1.482020e+001 -2.438600e+000 9.330127e+000 - endloop - endfacet - facet normal -5.944578e-017 -5.735764e-001 8.191520e-001 - outer loop - vertex -1.798000e-001 -2.438600e+000 9.330127e+000 - vertex -1.798000e-001 -3.152538e+000 8.830222e+000 - vertex 1.482020e+001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal 0.000000e+000 -7.071068e-001 7.071068e-001 - outer loop - vertex -1.798000e-001 -3.152538e+000 8.830222e+000 - vertex -1.798000e-001 -3.768822e+000 8.213938e+000 - vertex 1.482020e+001 -3.768822e+000 8.213938e+000 - endloop - endfacet - facet normal -3.821514e-017 -8.191520e-001 5.735764e-001 - outer loop - vertex -1.798000e-001 -3.768822e+000 8.213938e+000 - vertex -1.798000e-001 -4.268727e+000 7.500000e+000 - vertex 1.482020e+001 -4.268727e+000 7.500000e+000 - endloop - endfacet - facet normal 0.000000e+000 -9.063078e-001 4.226183e-001 - outer loop - vertex -1.798000e-001 -4.268727e+000 7.500000e+000 - vertex -1.798000e-001 -4.637063e+000 6.710101e+000 - vertex 1.482020e+001 -4.637063e+000 6.710101e+000 - endloop - endfacet - facet normal -1.910757e-017 -9.659258e-001 2.588190e-001 - outer loop - vertex -1.798000e-001 -4.637063e+000 6.710101e+000 - vertex -1.798000e-001 -4.862639e+000 5.868241e+000 - vertex 1.482020e+001 -4.862639e+000 5.868241e+000 - endloop - endfacet - facet normal -9.023020e-017 -9.961947e-001 8.715574e-002 - outer loop - vertex -1.798000e-001 -4.862639e+000 5.868241e+000 - vertex -1.798000e-001 -4.938600e+000 5.000000e+000 - vertex 1.482020e+001 -4.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 2.016910e-017 -9.961947e-001 -8.715574e-002 - outer loop - vertex -1.798000e-001 -4.938600e+000 5.000000e+000 - vertex -1.798000e-001 -4.862639e+000 4.131759e+000 - vertex 1.482020e+001 -4.862639e+000 4.131759e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -2.893023e+000 5.520945e+000 - vertex 4.982020e+001 -4.862639e+000 5.868241e+000 - vertex 4.982020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -2.893023e+000 5.520945e+000 - vertex 4.982020e+001 -4.637063e+000 6.710101e+000 - vertex 4.982020e+001 -4.862639e+000 5.868241e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -2.893023e+000 5.520945e+000 - vertex 4.982020e+001 -2.757678e+000 6.026060e+000 - vertex 4.982020e+001 -4.637063e+000 6.710101e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.637063e+000 6.710101e+000 - vertex 4.982020e+001 -2.757678e+000 6.026060e+000 - vertex 4.982020e+001 -4.268727e+000 7.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.268727e+000 7.500000e+000 - vertex 4.982020e+001 -2.757678e+000 6.026060e+000 - vertex 4.982020e+001 -2.536676e+000 6.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -3.768822e+000 8.213938e+000 - vertex 4.982020e+001 -2.536676e+000 6.500000e+000 - vertex 4.982020e+001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -1.866963e+000 7.298133e+000 - vertex 4.982020e+001 -3.768822e+000 8.213938e+000 - vertex 4.982020e+001 -2.236733e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -1.866963e+000 7.298133e+000 - vertex 4.982020e+001 -3.152538e+000 8.830222e+000 - vertex 4.982020e+001 -3.768822e+000 8.213938e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -1.866963e+000 7.298133e+000 - vertex 4.982020e+001 -1.438600e+000 7.598076e+000 - vertex 4.982020e+001 -3.152538e+000 8.830222e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -3.152538e+000 8.830222e+000 - vertex 4.982020e+001 -1.438600e+000 7.598076e+000 - vertex 4.982020e+001 -2.438600e+000 9.330127e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -2.438600e+000 9.330127e+000 - vertex 4.982020e+001 -1.438600e+000 7.598076e+000 - vertex 4.982020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -1.648701e+000 9.698463e+000 - vertex 4.982020e+001 -9.646604e-001 7.819078e+000 - vertex 4.982020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -8.068409e-001 9.924039e+000 - vertex 4.982020e+001 -4.595445e-001 7.954423e+000 - vertex 4.982020e+001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 6.140000e-002 1.000000e+001 - vertex 4.982020e+001 6.140000e-002 8.000000e+000 - vertex 4.982020e+001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 9.296409e-001 9.924039e+000 - vertex 4.982020e+001 5.823445e-001 7.954423e+000 - vertex 4.982020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 1.771501e+000 9.698463e+000 - vertex 4.982020e+001 1.087460e+000 7.819078e+000 - vertex 4.982020e+001 1.561400e+000 7.598076e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 2.561400e+000 9.330127e+000 - vertex 4.982020e+001 1.561400e+000 7.598076e+000 - vertex 4.982020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 3.275338e+000 8.830222e+000 - vertex 4.982020e+001 1.989763e+000 7.298133e+000 - vertex 4.982020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 3.891622e+000 8.213938e+000 - vertex 4.982020e+001 2.359533e+000 6.928363e+000 - vertex 4.982020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 3.891622e+000 8.213938e+000 - vertex 4.982020e+001 3.275338e+000 8.830222e+000 - vertex 4.982020e+001 2.359533e+000 6.928363e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 2.359533e+000 6.928363e+000 - vertex 4.982020e+001 2.659476e+000 6.500000e+000 - vertex 4.982020e+001 4.391527e+000 7.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 4.391527e+000 7.500000e+000 - vertex 4.982020e+001 2.659476e+000 6.500000e+000 - vertex 4.982020e+001 4.759863e+000 6.710101e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 4.759863e+000 6.710101e+000 - vertex 4.982020e+001 2.659476e+000 6.500000e+000 - vertex 4.982020e+001 2.880478e+000 6.026060e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 4.985439e+000 5.868241e+000 - vertex 4.982020e+001 2.880478e+000 6.026060e+000 - vertex 4.982020e+001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.982020e+001 3.015823e+000 5.520945e+000 - vertex 4.982020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 3.015823e+000 4.479055e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.982020e+001 3.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 3.015823e+000 4.479055e+000 - vertex 4.982020e+001 2.880478e+000 3.973940e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.982020e+001 2.880478e+000 3.973940e+000 - vertex 4.982020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 2.359533e+000 3.071637e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.982020e+001 2.659476e+000 3.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 2.359533e+000 3.071637e+000 - vertex 4.982020e+001 1.989763e+000 2.701867e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.982020e+001 1.989763e+000 2.701867e+000 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 5.000000e+000 - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 1.989763e+000 2.701867e+000 - vertex 4.982020e+001 1.561400e+000 2.401924e+000 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 2.506140e+001 0.000000e+000 - vertex 4.982020e+001 1.989763e+000 2.701867e+000 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 1.561400e+000 2.401924e+000 - vertex 4.982020e+001 1.087460e+000 2.180922e+000 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.982020e+001 1.087460e+000 2.180922e+000 - vertex 4.982020e+001 5.823445e-001 2.045577e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 6.140000e-002 2.000000e+000 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.982020e+001 5.823445e-001 2.045577e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 6.140000e-002 2.000000e+000 - vertex 4.982020e+001 -4.595445e-001 2.045577e+000 - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 6.140000e-002 -8.881784e-016 - vertex 4.982020e+001 -4.595445e-001 2.045577e+000 - vertex 4.982020e+001 -8.068409e-001 7.596123e-002 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -8.068409e-001 7.596123e-002 - vertex 4.982020e+001 -4.595445e-001 2.045577e+000 - vertex 4.982020e+001 -9.646604e-001 2.180922e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -1.648701e+000 3.015369e-001 - vertex 4.982020e+001 -9.646604e-001 2.180922e+000 - vertex 4.982020e+001 -1.438600e+000 2.401924e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -2.438600e+000 6.698730e-001 - vertex 4.982020e+001 -1.438600e+000 2.401924e+000 - vertex 4.982020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -3.152538e+000 1.169778e+000 - vertex 4.982020e+001 -1.866963e+000 2.701867e+000 - vertex 4.982020e+001 -3.768822e+000 1.786062e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -3.152538e+000 1.169778e+000 - vertex 4.982020e+001 -2.438600e+000 6.698730e-001 - vertex 4.982020e+001 -1.866963e+000 2.701867e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -1.866963e+000 2.701867e+000 - vertex 4.982020e+001 -2.236733e+000 3.071637e+000 - vertex 4.982020e+001 -3.768822e+000 1.786062e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -3.768822e+000 1.786062e+000 - vertex 4.982020e+001 -2.236733e+000 3.071637e+000 - vertex 4.982020e+001 -4.268727e+000 2.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.268727e+000 2.500000e+000 - vertex 4.982020e+001 -2.236733e+000 3.071637e+000 - vertex 4.982020e+001 -2.536676e+000 3.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.637063e+000 3.289899e+000 - vertex 4.982020e+001 -2.536676e+000 3.500000e+000 - vertex 4.982020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.862639e+000 4.131759e+000 - vertex 4.982020e+001 -2.757678e+000 3.973940e+000 - vertex 4.982020e+001 -2.893023e+000 4.479055e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.938600e+000 5.000000e+000 - vertex 4.982020e+001 -2.893023e+000 4.479055e+000 - vertex 4.982020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.862639e+000 5.868241e+000 - vertex 4.982020e+001 -4.938600e+000 5.000000e+000 - vertex 4.982020e+001 -2.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 5.061400e+000 5.000000e+000 - vertex 4.982020e+001 4.985439e+000 5.868241e+000 - vertex 4.982020e+001 3.015823e+000 5.520945e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 4.759863e+000 6.710101e+000 - vertex 4.982020e+001 2.880478e+000 6.026060e+000 - vertex 4.982020e+001 4.985439e+000 5.868241e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 3.275338e+000 8.830222e+000 - vertex 4.982020e+001 2.561400e+000 9.330127e+000 - vertex 4.982020e+001 1.989763e+000 7.298133e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 2.561400e+000 9.330127e+000 - vertex 4.982020e+001 1.771501e+000 9.698463e+000 - vertex 4.982020e+001 1.561400e+000 7.598076e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 1.771501e+000 9.698463e+000 - vertex 4.982020e+001 9.296409e-001 9.924039e+000 - vertex 4.982020e+001 1.087460e+000 7.819078e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 9.296409e-001 9.924039e+000 - vertex 4.982020e+001 6.140000e-002 1.000000e+001 - vertex 4.982020e+001 5.823445e-001 7.954423e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 6.140000e-002 1.000000e+001 - vertex 4.982020e+001 -8.068409e-001 9.924039e+000 - vertex 4.982020e+001 6.140000e-002 8.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -8.068409e-001 9.924039e+000 - vertex 4.982020e+001 -1.648701e+000 9.698463e+000 - vertex 4.982020e+001 -4.595445e-001 7.954423e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -1.648701e+000 9.698463e+000 - vertex 4.982020e+001 -2.438600e+000 9.330127e+000 - vertex 4.982020e+001 -9.646604e-001 7.819078e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -3.768822e+000 8.213938e+000 - vertex 4.982020e+001 -4.268727e+000 7.500000e+000 - vertex 4.982020e+001 -2.536676e+000 6.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.862639e+000 4.131759e+000 - vertex 4.982020e+001 -2.893023e+000 4.479055e+000 - vertex 4.982020e+001 -4.938600e+000 5.000000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.862639e+000 4.131759e+000 - vertex 4.982020e+001 -4.637063e+000 3.289899e+000 - vertex 4.982020e+001 -2.757678e+000 3.973940e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -4.637063e+000 3.289899e+000 - vertex 4.982020e+001 -4.268727e+000 2.500000e+000 - vertex 4.982020e+001 -2.536676e+000 3.500000e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -2.438600e+000 6.698730e-001 - vertex 4.982020e+001 -1.648701e+000 3.015369e-001 - vertex 4.982020e+001 -1.438600e+000 2.401924e+000 - endloop - endfacet - facet normal 1.000000e+000 0.000000e+000 0.000000e+000 - outer loop - vertex 4.982020e+001 -8.068409e-001 7.596123e-002 - vertex 4.982020e+001 -9.646604e-001 2.180922e+000 - vertex 4.982020e+001 -1.648701e+000 3.015369e-001 - endloop - endfacet -endsolid From 821b73738a3d2654fb099cb49757a07257c3f55c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 6 Jul 2023 11:00:57 +0330 Subject: [PATCH 536/775] OpenSCAD script to generate I-shaped beam --- files/beam-I-shaped.scad | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 files/beam-I-shaped.scad diff --git a/files/beam-I-shaped.scad b/files/beam-I-shaped.scad new file mode 100644 index 000000000..1711bad05 --- /dev/null +++ b/files/beam-I-shaped.scad @@ -0,0 +1,26 @@ +// Parameters +length = 200; // Length of the beam +width = 25; // Width of the beam +height = 25+4+4; // Overall height of the beam +thickness = 4; // Thickness of the beam + +// Derived parameters +flange_height = 4; // Height of the top and bottom flanges +web_height = height - 2 * flange_height; // Height of the vertical web + +// I-beam structure +module ibeam() { + // Top flange + translate([0, 0, height - flange_height]) + cube([length, width, flange_height]); + + // Bottom flange + cube([length, width, flange_height]); + + // Vertical web + translate([0, (width - thickness) / 2, flange_height]) + cube([length, thickness, web_height]); +} + +// Generate the I-beam +ibeam(); \ No newline at end of file From 4861bc84ad59fc29c2c7c40f61bbaf185d0813cf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 6 Jul 2023 11:36:21 +0330 Subject: [PATCH 537/775] OpenSCAD script to generate square beam --- files/beam-square.scad | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 files/beam-square.scad diff --git a/files/beam-square.scad b/files/beam-square.scad new file mode 100644 index 000000000..ef90bfaf4 --- /dev/null +++ b/files/beam-square.scad @@ -0,0 +1,6 @@ +length = 200; +width = 17.32; +height = 17.32; + +//translate([0, -width/2, 0]) +cube([length, width, height]); From c2b843312a3a5b543bd9cefac3752aaaa9e7dc23 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 6 Jul 2023 11:54:17 +0330 Subject: [PATCH 538/775] OpenSCAD script to generate circle beam --- files/beam-circle.scad | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 files/beam-circle.scad diff --git a/files/beam-circle.scad b/files/beam-circle.scad new file mode 100644 index 000000000..ae77f5750 --- /dev/null +++ b/files/beam-circle.scad @@ -0,0 +1,6 @@ +length = 200; +diameter = 19.54; + +translate([0, 0, diameter/2]) +rotate([0,90,0]) +cylinder(h= length, d=diameter); \ No newline at end of file From 6dc4f361c6e08d6d4c3b46ba45f7f138d5a5663d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 6 Jul 2023 12:22:44 +0330 Subject: [PATCH 539/775] OpenSCAD script to generate pipe beam --- files/beam-pipe.scad | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 files/beam-pipe.scad diff --git a/files/beam-pipe.scad b/files/beam-pipe.scad new file mode 100644 index 000000000..25d62c3f5 --- /dev/null +++ b/files/beam-pipe.scad @@ -0,0 +1,13 @@ +l = 200; +d = 27.87; +t = 4; + +translate([0, 0, d/2]) +rotate([0,90,0]) +difference() { + // Outer cylinder + cylinder(d=d, h=l); + + // Inner cylinder + cylinder(d=d-2*t, h=l); +} \ No newline at end of file From 85573a926c796be4092077ac91623a762382533f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 8 Jul 2023 10:19:57 +0330 Subject: [PATCH 540/775] Rename file --- files/{beam-I-shaped.scad => beam-I.scad} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename files/{beam-I-shaped.scad => beam-I.scad} (100%) diff --git a/files/beam-I-shaped.scad b/files/beam-I.scad similarity index 100% rename from files/beam-I-shaped.scad rename to files/beam-I.scad From 4bb1becef82545e1a97edbb4f6c19d615c353cc8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 8 Jul 2023 10:43:24 +0330 Subject: [PATCH 541/775] STL files for simple 3D beams --- files/beam-I.stl | Bin 0 -> 2284 bytes files/beam-circle.stl | Bin 0 -> 5884 bytes files/beam-pipe.stl | Bin 0 -> 12084 bytes files/beam-square.stl | Bin 0 -> 684 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 files/beam-I.stl create mode 100644 files/beam-circle.stl create mode 100644 files/beam-pipe.stl create mode 100644 files/beam-square.stl diff --git a/files/beam-I.stl b/files/beam-I.stl new file mode 100644 index 0000000000000000000000000000000000000000..d612cfa5b6c5ae98a65cc920c6ac95ed3d1a9df1 GIT binary patch literal 2284 zcmbu9F;c`Z3`Jc~aSF;UxC6UDLBmjR1$HI{102COqs>u#4D>AjSn+zGz%xm-U;pb% zcCs&D=a1Ki)8oza=iB-HI{kOu)&lvi*LiwKX+5QMb)ORPVsWucIB`m&BC-xa0iKUD z#cCOOjEd4dGFo@%Ia8?8WmmCoR1?oVme#MPg{gQx2Oea!SBmA`y2?~?R#dEY(!Kg} z4%c3)!T;_ms^y2!ah)U??JgO`!kx_>1=F%%u|}3~&*pD`F6L3}(vB(?ZmirDkp&u9 z)em)F@&HlYL+}%B&rEC&>k1FC9Mzi<@mL$y8k`r4{R|v$=g}rs&B($}3h+{^{pK+$ z<{t9m85L`-4_ZAkk*~-Srsv#a+4|j|IUZ#?2Ogf;pCI_$BPv#7>0Mg3O5{CunPANxcR?Q`wu&+cLh1VhNYJDVoQ~Dzy{eH^rBok)bZD*Nw4GamI@3=8wWvq>3z2L_;}`0z|y`c_FPponliB~QiI1Z0}S;Zr|t20<~@V9tNj=EILFd@ q2PZCe;ink9DLmXVV#zO7GDVo<5cY?-*u{!*Q)G9K8Dc!}Q~U$;ME#Ed literal 0 HcmV?d00001 diff --git a/files/beam-circle.stl b/files/beam-circle.stl new file mode 100644 index 0000000000000000000000000000000000000000..69991d922a9e79f2ec11eb35eeca552ab2f82407 GIT binary patch literal 5884 zcmbuDKd2p55XKKe3@F$r0gZ(qR;Cmb#QTS9af{>yNe~GHQY82X(MXKsrFblMfe5h> zLI}}P5F1}%lXv$%0(OdsQ7a(|K|vH-MR2~EGiSb8vs!qYH#uj1^X=|A=iAvFK7H!7 zBa8X7j~sga+)8g>n#_bmAht7ynk#`%5stCg5a#26Ewy* zpS(6XeeR5E#LRNB=g8LVlc!&pLLR1G&VIl7t7^n} zCOE4U&I%gDV+S9fUY|@L6j0Rwqs0>wFT&KK30k;Fq6NIiu&B}Fy1|cih`Y{5uA2FT@&eDC=>dLvPGzd9Sy`4clIlF#pIg4W^vWA@C zMn?<{afV*JU7bN3VAnm0vp8l#&vvb=-qq-+1P$@T-aJv=a@W0B3z-RJG9>>Xuy>+e3)^(>B=(6?91!reL@F|NO^#|kl? zyT8LZi(@A2Sy|moMT$J9w$J0 zFT!*tWQI;o5Uz{A;{<5G4`jMtCgcvQf8;KMwZ{q2z8~J zgzUKH$V{;II04$v2h*A0_XHEHJx+l3bIx=o!~yEt(%x!Lu=Y3s+TDlsGQsa{CRjTY zoW(Ta=84*`W2d3Z5TZIKf6H3@-vnsy8Q{C#ap*U#N!0Ii?-Q8_Z8;z5s^pneujQ}% z{2iSMS*hxrnTSe54JHs%$I;#rSwnVQbx!`D35$JKjuW808wkDORmsVz&Z!+oBSQP% z2+-7Jw6{dQDsh17ocupi`O9*g08L#+drM>ji*HV*eL^Ebdw3sAAhsXVmFQ@ueXG@U z`IEma^HqiSarct@6(yQRI9Vp5((pc*KXLyd4U`_gkFDh;0%6Ns&cXL_h1o>85XyMBw^gY$hbf!O^j Y^oAPYmi+Z%vAgy^HM}mouzb`pD}oJ~v>Qgj%(xRyMPp?gZxC zV$`h`pZwwPrZo{W8_!|Y=iG>h-B?jd*R|qvzR5YamW)`k8C=Nx_vi3obKZ%a?X(IX z5hXtVo$jr|Sb0CtL#}i5T>8|XS0dtyJxn^rjn6$wRuNaNSu`9(T?T?EUCO_@I^2S+;7I@32+7x3S@Im1Cm%5vw^y1T9HIt#sU~u6WNkW2`*d7mW5C z(a`)dR-N!w+h?%SHddpiv7&7M(Dm$5a=^&2=ow`tsukuycATLM8HI@5=TDtpeE!@W z9!naP+Nw&Z)l9R6m3Zy@-?+H-#Dnf5>#bwu#1g$`tFHLeCq}EHUTv+eCJ@g(_9`3Q zZ#kj!k+Con=!e!ze`p~UwYCcVc>MhPMn5>Z7=@r`AKF_Tg&en;(6(!zlAej5edM28 z-+t`--m2_vjp;fcYNd4gn|)yCFdaMmB^ZoBX-W*zxAV2 zPq>eyXCn8Booyx3_i@B?SHE)W?bq(QkECY;@yLBiiS&IO5%iw>NcuR!toGTeq&u<1 z6GS`qBAy@)6WB#(A4*tn_c^*r&pxn2GLumvYnpv1VY9Z+C`o$up&61AS<~!8t(3M% z+>cc-`><#~;69jEHSenHL#>py^ z(<&4^e9u1AN@-{bGxFLGXvX(`{!90fRy*5C&pwoZe#jYTjSpzX*{?q0K9tCsW*f3IlELqygzw@L|=4hK^Z2p#aR5u}Fz@cNzGfd14av#zG0r;lPsidyU@Oc)s+JMOh;QW%gFfuybNrSJYveXEi?w zuXuLGdS<4NRm99GpTmQlojXx;9JNXsghdHX^nO0a%3-#oR$5k~`cOK{z1MK%e>h=r zJtIokTaES{Ss-dP(;Vqam@@R7Dx#9>F;~G+t)lk9AL~_r)ko%3x(4eFBz8^X!+9#!}56#sqGDbFOF_szGSR3fOS}Cpmst>J8 z^ERa`VG7W5!`770n${DVw<%o-(~psPDWSgC6PoEMT?vd=WO}VBp}yA>pd-ty^m;<` zHl-^8<>Z^HnP6+z6PmXvT?uG7-)$+OzSk3(&zZiC9Ccpj&_SL|lu+O9V~MfApIRxM zdDrX%YRMCpS}9$9sFl*0Ma@2-uRJNLmC|*rOc};aqpj_ce`-y&Ra&oFDP0LwGUx}j z3mU__*V-y508j2}rF8Y7R!T!-c!yklKr?s)p;k&)A8MsEw1jVdst;&J+^W>OX{FZ_ z&<|!c>wQ2o;&!OMOH<#~hZ4|_$h9h62`En7a@F@ZT2m#kMxMTeo3u)3P3wuE<6cZ# zSP5tbTct#l!}odu`oW$nT?uFgM^_2;y`F%6a0ZpG1hj-vqJ;Xc1T=#Yr!*9UF|Q~aS` zo~l*t;DZ@wZIxwY{XFP7)v!{!653lG1#Mw%m3p839i7AJ_~^K)zuGF)D;et;QT0~| z9e1VGUu##{ySpd)cNsY!JKGs!eseb>Q3fho(Wq7v){oq|z zKF2&KVRtXX%6I)v*WAb64_T zw%^p>ZDZDWdxps8{Z*FXBMGZltd!QWf4ze*IsD9tSmIq@T1E84bNJ}rei#uE$5tgB zF~;X@X)|~o=NvW2Jdbh9=O`uNaW%$At?KC7JNofWk*?ZQiMSo4ipHC2el4O_N^7~b z)Ak*}ulsiZMvS)rW;M>ZT2`XIA5c2W=w1Js%ICx8V7vv;IL_yls8Ov}NrU)>#noH= zTZ1|#m~*}*&2lAFKPsJL2*UJgMZJP|zUM-#=p&ySuuLM}L2yr1tEAyW_bF4+ewR_- zfa5u}eGp5;uKqI9+@pL3H)GDDx4d0OWbi$Amf^voq!YRiRvKf)np(SPcb32PZ;Ikg z6?aZ+Ro@5et+NukTUNTZ>K4=XFZ6F9p|5;@3RRQ$oFn6G%Ov#8ap*2Hz@*W0BR1#* zIwqkT-qtA#Q)7?iWsukKUkvNoSsHornDX&C5_<;VJ~FC9QK?<|+?wj&az?Av%Ih6xL)9)PHkg+n!kJ&8Ror*;ImQFuaxyPT zt7yCAD4hmj8Ne!X23P8_e_%~eakQ*NtPfg2Yhw?u?}UB-SjGNfGd0#-Rqd+Ow&Qf7 zS}C1n^uyNRD%POhvBoaSbIqYu+lgw0RTL|@YCgR1jd<19T&eM#>wgd^;O4h0!(lpB G@c#h1;8NcJ literal 0 HcmV?d00001 diff --git a/files/beam-square.stl b/files/beam-square.stl new file mode 100644 index 0000000000000000000000000000000000000000..011725b2e0bc104a14f4972db20028474b628db8 GIT binary patch literal 684 zcmbtRF%E+;5X+4Ei2kHPbm&rbU}c02wSB_PU3d~-BaU<21&|mT3F7!{=aRg>!@F(j z`}O(hhp`I(jtc`MPdCin^sDiO@Mv@mY&_NYOLTaZcT>eA=a>xxF_#>Z*18Z$ba>TT zPv9&cqOwCU-i7=iM=B_lC+3Nv#_+km!}6|hM> Date: Sat, 8 Jul 2023 10:56:53 +0330 Subject: [PATCH 542/775] Simpler OpenSCAD script --- files/beam-I.scad | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/files/beam-I.scad b/files/beam-I.scad index 1711bad05..a202d6782 100644 --- a/files/beam-I.scad +++ b/files/beam-I.scad @@ -1,26 +1,16 @@ -// Parameters -length = 200; // Length of the beam -width = 25; // Width of the beam -height = 25+4+4; // Overall height of the beam -thickness = 4; // Thickness of the beam +t = 4; // Thickness +length = 200; // Length of the beam +width = 25; // Width of the beam +height = 25 + t + t; // Overall height of the beam -// Derived parameters -flange_height = 4; // Height of the top and bottom flanges +flange_height = t; // Height of the top and bottom flanges web_height = height - 2 * flange_height; // Height of the vertical web -// I-beam structure -module ibeam() { - // Top flange - translate([0, 0, height - flange_height]) - cube([length, width, flange_height]); +// Top flange +translate([ 0, 0, height - flange_height ]) cube([ length, width, flange_height ]); - // Bottom flange - cube([length, width, flange_height]); +// Bottom flange +cube([ length, width, flange_height ]); - // Vertical web - translate([0, (width - thickness) / 2, flange_height]) - cube([length, thickness, web_height]); -} - -// Generate the I-beam -ibeam(); \ No newline at end of file +// Vertical web +translate([ 0, (width - t) / 2, flange_height ]) cube([ length, t, web_height ]); \ No newline at end of file From c885f0606ca631a3e8680793883c71d0117fbcda Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 8 Jul 2023 10:59:32 +0330 Subject: [PATCH 543/775] Format OpenSCAD scripts --- files/beam-circle.scad | 4 +--- files/beam-pipe.scad | 15 +++++++-------- files/beam-square.scad | 4 ++-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/files/beam-circle.scad b/files/beam-circle.scad index ae77f5750..b33360fc3 100644 --- a/files/beam-circle.scad +++ b/files/beam-circle.scad @@ -1,6 +1,4 @@ length = 200; diameter = 19.54; -translate([0, 0, diameter/2]) -rotate([0,90,0]) -cylinder(h= length, d=diameter); \ No newline at end of file +translate([ 0, 0, diameter / 2 ]) rotate([ 0, 90, 0 ]) cylinder(h = length, d = diameter); \ No newline at end of file diff --git a/files/beam-pipe.scad b/files/beam-pipe.scad index 25d62c3f5..c109a5d9b 100644 --- a/files/beam-pipe.scad +++ b/files/beam-pipe.scad @@ -2,12 +2,11 @@ l = 200; d = 27.87; t = 4; -translate([0, 0, d/2]) -rotate([0,90,0]) -difference() { - // Outer cylinder - cylinder(d=d, h=l); - - // Inner cylinder - cylinder(d=d-2*t, h=l); +translate([ 0, 0, d / 2 ]) rotate([ 0, 90, 0 ]) difference() +{ + // Outer cylinder + cylinder(d = d, h = l); + + // Inner cylinder + cylinder(d = d - 2 * t, h = l); } \ No newline at end of file diff --git a/files/beam-square.scad b/files/beam-square.scad index ef90bfaf4..d03d154a1 100644 --- a/files/beam-square.scad +++ b/files/beam-square.scad @@ -2,5 +2,5 @@ length = 200; width = 17.32; height = 17.32; -//translate([0, -width/2, 0]) -cube([length, width, height]); +// translate([0, -width/2, 0]) +cube([ length, width, height ]); \ No newline at end of file From 39c133300502664a1be99b8544e33e2df945ef2e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 8 Jul 2023 11:53:02 +0330 Subject: [PATCH 544/775] Test pipe --- examples/finite_elements/main.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 22380a7ff..20526d531 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -68,7 +68,7 @@ func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shap // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - stl := "../../files/teapot.stl" + stl := "../../files/beam-pipe.stl" // read the stl file. file, err := os.OpenFile(stl, os.O_RDONLY, 0400) @@ -89,7 +89,7 @@ func main() { } // tet4 i.e. 4-node tetrahedron - err = fePartial(inSdf, 50, render.Linear, render.Tetrahedral, "partial-tet4.inp", 0, 15) + err = fePartial(inSdf, 50, render.Linear, render.Tetrahedral, "partial-tet4.inp", 0, 3) if err != nil { log.Fatalf("error: %s", err) } @@ -101,7 +101,7 @@ func main() { } // tet10 i.e. 10-node tetrahedron - err = fePartial(inSdf, 50, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", 0, 15) + err = fePartial(inSdf, 50, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", 0, 3) if err != nil { log.Fatalf("error: %s", err) } @@ -113,7 +113,7 @@ func main() { } // hex8 i.e. 8-node hexahedron - err = fePartial(inSdf, 50, render.Linear, render.Hexahedral, "partial-hex8.inp", 0, 15) + err = fePartial(inSdf, 50, render.Linear, render.Hexahedral, "partial-hex8.inp", 0, 3) if err != nil { log.Fatalf("error: %s", err) } @@ -125,7 +125,7 @@ func main() { } // hex20 i.e. 20-node hexahedron - err = fePartial(inSdf, 50, render.Quadratic, render.Hexahedral, "partial-hex20.inp", 0, 15) + err = fePartial(inSdf, 50, render.Quadratic, render.Hexahedral, "partial-hex20.inp", 0, 3) if err != nil { log.Fatalf("error: %s", err) } @@ -137,7 +137,7 @@ func main() { } // hex8 and tet4 - err = fePartial(inSdf, 50, render.Linear, render.Both, "partial-hex8tet4.inp", 0, 15) + err = fePartial(inSdf, 50, render.Linear, render.Both, "partial-hex8tet4.inp", 0, 3) if err != nil { log.Fatalf("error: %s", err) } @@ -149,7 +149,7 @@ func main() { } // hex20 and tet10 - err = fePartial(inSdf, 50, render.Quadratic, render.Both, "partial-hex20tet10.inp", 0, 15) + err = fePartial(inSdf, 50, render.Quadratic, render.Both, "partial-hex20tet10.inp", 0, 3) if err != nil { log.Fatalf("error: %s", err) } From b02f974d2f3e4068778dee51ce6cfd1f3f893988 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 11 Jul 2023 10:04:48 +0330 Subject: [PATCH 545/775] Update read-me: openSUSE Leap: from 15.4 to 15.5 --- examples/finite_elements/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 92f8cdf4d..31aabb3f4 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -26,10 +26,10 @@ CalculiX and CalculiX GraphiX binaries are available for different platforms, li openSUSE has [CCX](https://software.opensuse.org/package/ccx) package and also [CGX](https://software.opensuse.org/package/cgx) one. -To install CCX and CGX on openSUSE Leap 15.4 you can run as root: +To install CCX and CGX on openSUSE Leap 15.5 you can run as root: ```bash -zypper addrepo https://download.opensuse.org/repositories/science/15.4/science.repo +zypper addrepo https://download.opensuse.org/repositories/science/15.5/science.repo zypper refresh zypper install ccx zypper install cgx From e69d79c0c8fa0fdda201bd59d62f153815da26c7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 11 Jul 2023 17:19:42 +0330 Subject: [PATCH 546/775] Start an easy way to set restraints and loads --- examples/finite_elements/benchmark-I.go | 1 + examples/finite_elements/benchmark-circule.go | 1 + examples/finite_elements/benchmark-pipe.go | 1 + examples/finite_elements/benchmark-squre.go | 123 ++++++++++++++++++ examples/finite_elements/main.go | 104 ++------------- files/beam-I.stl | Bin 2284 -> 0 bytes files/beam-circle.stl | Bin 5884 -> 0 bytes files/beam-pipe.stl | Bin 12084 -> 0 bytes files/beam-square.stl | Bin 684 -> 0 bytes render/finiteelements/mesh/fem.go | 8 +- render/finiteelements/mesh/inp.go | 8 ++ 11 files changed, 152 insertions(+), 94 deletions(-) create mode 100644 examples/finite_elements/benchmark-I.go create mode 100644 examples/finite_elements/benchmark-circule.go create mode 100644 examples/finite_elements/benchmark-pipe.go create mode 100644 examples/finite_elements/benchmark-squre.go delete mode 100644 files/beam-I.stl delete mode 100644 files/beam-circle.stl delete mode 100644 files/beam-pipe.stl delete mode 100644 files/beam-square.stl diff --git a/examples/finite_elements/benchmark-I.go b/examples/finite_elements/benchmark-I.go new file mode 100644 index 000000000..06ab7d0f9 --- /dev/null +++ b/examples/finite_elements/benchmark-I.go @@ -0,0 +1 @@ +package main diff --git a/examples/finite_elements/benchmark-circule.go b/examples/finite_elements/benchmark-circule.go new file mode 100644 index 000000000..06ab7d0f9 --- /dev/null +++ b/examples/finite_elements/benchmark-circule.go @@ -0,0 +1 @@ +package main diff --git a/examples/finite_elements/benchmark-pipe.go b/examples/finite_elements/benchmark-pipe.go new file mode 100644 index 000000000..06ab7d0f9 --- /dev/null +++ b/examples/finite_elements/benchmark-pipe.go @@ -0,0 +1 @@ +package main diff --git a/examples/finite_elements/benchmark-squre.go b/examples/finite_elements/benchmark-squre.go new file mode 100644 index 000000000..8397c56ac --- /dev/null +++ b/examples/finite_elements/benchmark-squre.go @@ -0,0 +1,123 @@ +package main + +import ( + "fmt" + "log" + "os" + "os/exec" + + "github.com/deadsy/sdfx/obj" + "github.com/deadsy/sdfx/render" +) + +func bmSquareRestraint(x, y, z float64) (bool, bool, bool) { + return false, false, false +} + +func bmSquareLoad(x, y, z float64) (float64, float64, float64) { + return 0, 0, 0 +} + +// Benchmark reference: +// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections +func benchmarkSquare() { + prg := "openscad" + + arg1 := "-o" + arg2_stl := "3d-beam-square.stl" + arg3_cad := "../../files/beam-square.scad" + + cmd := exec.Command(prg, arg1, arg2_stl, arg3_cad) + stdout, err := cmd.Output() + + if err != nil { + log.Fatalf("error: %s", err) + return + } + + fmt.Println(string(stdout)) + + // read the stl file. + file, err := os.OpenFile(arg2_stl, os.O_RDONLY, 0400) + if err != nil { + log.Fatalf("error: %s", err) + } + + // create the SDF from the STL mesh + inSdf, err := obj.ImportSTL(file, 20, 3, 5) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet4 i.e. 4-node tetrahedron + err = fe(inSdf, 50, render.Linear, render.Tetrahedral, "tet4.inp", bmSquareRestraint, bmSquareLoad) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet4 i.e. 4-node tetrahedron + err = fePartial(inSdf, 50, render.Linear, render.Tetrahedral, "partial-tet4.inp", bmSquareRestraint, bmSquareLoad, 0, 3) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet10 i.e. 10-node tetrahedron + err = fe(inSdf, 50, render.Quadratic, render.Tetrahedral, "tet10.inp", bmSquareRestraint, bmSquareLoad) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet10 i.e. 10-node tetrahedron + err = fePartial(inSdf, 50, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", bmSquareRestraint, bmSquareLoad, 0, 3) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 i.e. 8-node hexahedron + err = fe(inSdf, 50, render.Linear, render.Hexahedral, "hex8.inp", bmSquareRestraint, bmSquareLoad) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 i.e. 8-node hexahedron + err = fePartial(inSdf, 50, render.Linear, render.Hexahedral, "partial-hex8.inp", bmSquareRestraint, bmSquareLoad, 0, 3) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 i.e. 20-node hexahedron + err = fe(inSdf, 50, render.Quadratic, render.Hexahedral, "hex20.inp", bmSquareRestraint, bmSquareLoad) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 i.e. 20-node hexahedron + err = fePartial(inSdf, 50, render.Quadratic, render.Hexahedral, "partial-hex20.inp", bmSquareRestraint, bmSquareLoad, 0, 3) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 and tet4 + err = fe(inSdf, 50, render.Linear, render.Both, "hex8tet4.inp", bmSquareRestraint, bmSquareLoad) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 and tet4 + err = fePartial(inSdf, 50, render.Linear, render.Both, "partial-hex8tet4.inp", bmSquareRestraint, bmSquareLoad, 0, 3) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 and tet10 + err = fe(inSdf, 50, render.Quadratic, render.Both, "hex20tet10.inp", bmSquareRestraint, bmSquareLoad) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 and tet10 + err = fePartial(inSdf, 50, render.Quadratic, render.Both, "partial-hex20tet10.inp", bmSquareRestraint, bmSquareLoad, 0, 3) + if err != nil { + log.Fatalf("error: %s", err) + } +} diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 20526d531..79cd842f7 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -10,11 +10,8 @@ Output `inp` file is consumable by ABAQUS or CalculiX. package main import ( - "log" "math" - "os" - "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" "github.com/deadsy/sdfx/render/finiteelements/mesh" "github.com/deadsy/sdfx/sdf" @@ -41,116 +38,39 @@ func dilationErosion(s sdf.SDF3) sdf.SDF3 { } // Generate finite elements. -func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string) error { +func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, + restraint func(x, y, z float64) (bool, bool, bool), + load func(x, y, z float64) (float64, float64, float64), +) error { s = dilationErosion(s) // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write all layers of mesh to file. - return m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + return m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3, restraint, load) } // Generate finite elements. // Only from a start layer to an end layer along the Z axis. // Applicable to 3D print analysis that is done layer-by-layer. -func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, layerStart, layerEnd int) error { +func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, + restraint func(x, y, z float64) (bool, bool, bool), + load func(x, y, z float64) (float64, float64, float64), + layerStart, layerEnd int, +) error { s = dilationErosion(s) // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to file. - return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3) + return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3, restraint, load) } // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - stl := "../../files/beam-pipe.stl" - - // read the stl file. - file, err := os.OpenFile(stl, os.O_RDONLY, 0400) - if err != nil { - log.Fatalf("error: %s", err) - } - - // create the SDF from the STL mesh - inSdf, err := obj.ImportSTL(file, 20, 3, 5) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet4 i.e. 4-node tetrahedron - err = fe(inSdf, 50, render.Linear, render.Tetrahedral, "tet4.inp") - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet4 i.e. 4-node tetrahedron - err = fePartial(inSdf, 50, render.Linear, render.Tetrahedral, "partial-tet4.inp", 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet10 i.e. 10-node tetrahedron - err = fe(inSdf, 50, render.Quadratic, render.Tetrahedral, "tet10.inp") - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet10 i.e. 10-node tetrahedron - err = fePartial(inSdf, 50, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 i.e. 8-node hexahedron - err = fe(inSdf, 50, render.Linear, render.Hexahedral, "hex8.inp") - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 i.e. 8-node hexahedron - err = fePartial(inSdf, 50, render.Linear, render.Hexahedral, "partial-hex8.inp", 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 i.e. 20-node hexahedron - err = fe(inSdf, 50, render.Quadratic, render.Hexahedral, "hex20.inp") - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 i.e. 20-node hexahedron - err = fePartial(inSdf, 50, render.Quadratic, render.Hexahedral, "partial-hex20.inp", 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 and tet4 - err = fe(inSdf, 50, render.Linear, render.Both, "hex8tet4.inp") - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 and tet4 - err = fePartial(inSdf, 50, render.Linear, render.Both, "partial-hex8tet4.inp", 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 and tet10 - err = fe(inSdf, 50, render.Quadratic, render.Both, "hex20tet10.inp") - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 and tet10 - err = fePartial(inSdf, 50, render.Quadratic, render.Both, "partial-hex20tet10.inp", 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } + benchmarkSquare() } diff --git a/files/beam-I.stl b/files/beam-I.stl deleted file mode 100644 index d612cfa5b6c5ae98a65cc920c6ac95ed3d1a9df1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2284 zcmbu9F;c`Z3`Jc~aSF;UxC6UDLBmjR1$HI{102COqs>u#4D>AjSn+zGz%xm-U;pb% zcCs&D=a1Ki)8oza=iB-HI{kOu)&lvi*LiwKX+5QMb)ORPVsWucIB`m&BC-xa0iKUD z#cCOOjEd4dGFo@%Ia8?8WmmCoR1?oVme#MPg{gQx2Oea!SBmA`y2?~?R#dEY(!Kg} z4%c3)!T;_ms^y2!ah)U??JgO`!kx_>1=F%%u|}3~&*pD`F6L3}(vB(?ZmirDkp&u9 z)em)F@&HlYL+}%B&rEC&>k1FC9Mzi<@mL$y8k`r4{R|v$=g}rs&B($}3h+{^{pK+$ z<{t9m85L`-4_ZAkk*~-Srsv#a+4|j|IUZ#?2Ogf;pCI_$BPv#7>0Mg3O5{CunPANxcR?Q`wu&+cLh1VhNYJDVoQ~Dzy{eH^rBok)bZD*Nw4GamI@3=8wWvq>3z2L_;}`0z|y`c_FPponliB~QiI1Z0}S;Zr|t20<~@V9tNj=EILFd@ q2PZCe;ink9DLmXVV#zO7GDVo<5cY?-*u{!*Q)G9K8Dc!}Q~U$;ME#Ed diff --git a/files/beam-circle.stl b/files/beam-circle.stl deleted file mode 100644 index 69991d922a9e79f2ec11eb35eeca552ab2f82407..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5884 zcmbuDKd2p55XKKe3@F$r0gZ(qR;Cmb#QTS9af{>yNe~GHQY82X(MXKsrFblMfe5h> zLI}}P5F1}%lXv$%0(OdsQ7a(|K|vH-MR2~EGiSb8vs!qYH#uj1^X=|A=iAvFK7H!7 zBa8X7j~sga+)8g>n#_bmAht7ynk#`%5stCg5a#26Ewy* zpS(6XeeR5E#LRNB=g8LVlc!&pLLR1G&VIl7t7^n} zCOE4U&I%gDV+S9fUY|@L6j0Rwqs0>wFT&KK30k;Fq6NIiu&B}Fy1|cih`Y{5uA2FT@&eDC=>dLvPGzd9Sy`4clIlF#pIg4W^vWA@C zMn?<{afV*JU7bN3VAnm0vp8l#&vvb=-qq-+1P$@T-aJv=a@W0B3z-RJG9>>Xuy>+e3)^(>B=(6?91!reL@F|NO^#|kl? zyT8LZi(@A2Sy|moMT$J9w$J0 zFT!*tWQI;o5Uz{A;{<5G4`jMtCgcvQf8;KMwZ{q2z8~J zgzUKH$V{;II04$v2h*A0_XHEHJx+l3bIx=o!~yEt(%x!Lu=Y3s+TDlsGQsa{CRjTY zoW(Ta=84*`W2d3Z5TZIKf6H3@-vnsy8Q{C#ap*U#N!0Ii?-Q8_Z8;z5s^pneujQ}% z{2iSMS*hxrnTSe54JHs%$I;#rSwnVQbx!`D35$JKjuW808wkDORmsVz&Z!+oBSQP% z2+-7Jw6{dQDsh17ocupi`O9*g08L#+drM>ji*HV*eL^Ebdw3sAAhsXVmFQ@ueXG@U z`IEma^HqiSarct@6(yQRI9Vp5((pc*KXLyd4U`_gkFDh;0%6Ns&cXL_h1o>85XyMBw^gY$hbf!O^j Y^oAPYmi+Z%vAgy^HM}mouzb`pD}oJ~v>Qgj%(xRyMPp?gZxC zV$`h`pZwwPrZo{W8_!|Y=iG>h-B?jd*R|qvzR5YamW)`k8C=Nx_vi3obKZ%a?X(IX z5hXtVo$jr|Sb0CtL#}i5T>8|XS0dtyJxn^rjn6$wRuNaNSu`9(T?T?EUCO_@I^2S+;7I@32+7x3S@Im1Cm%5vw^y1T9HIt#sU~u6WNkW2`*d7mW5C z(a`)dR-N!w+h?%SHddpiv7&7M(Dm$5a=^&2=ow`tsukuycATLM8HI@5=TDtpeE!@W z9!naP+Nw&Z)l9R6m3Zy@-?+H-#Dnf5>#bwu#1g$`tFHLeCq}EHUTv+eCJ@g(_9`3Q zZ#kj!k+Con=!e!ze`p~UwYCcVc>MhPMn5>Z7=@r`AKF_Tg&en;(6(!zlAej5edM28 z-+t`--m2_vjp;fcYNd4gn|)yCFdaMmB^ZoBX-W*zxAV2 zPq>eyXCn8Booyx3_i@B?SHE)W?bq(QkECY;@yLBiiS&IO5%iw>NcuR!toGTeq&u<1 z6GS`qBAy@)6WB#(A4*tn_c^*r&pxn2GLumvYnpv1VY9Z+C`o$up&61AS<~!8t(3M% z+>cc-`><#~;69jEHSenHL#>py^ z(<&4^e9u1AN@-{bGxFLGXvX(`{!90fRy*5C&pwoZe#jYTjSpzX*{?q0K9tCsW*f3IlELqygzw@L|=4hK^Z2p#aR5u}Fz@cNzGfd14av#zG0r;lPsidyU@Oc)s+JMOh;QW%gFfuybNrSJYveXEi?w zuXuLGdS<4NRm99GpTmQlojXx;9JNXsghdHX^nO0a%3-#oR$5k~`cOK{z1MK%e>h=r zJtIokTaES{Ss-dP(;Vqam@@R7Dx#9>F;~G+t)lk9AL~_r)ko%3x(4eFBz8^X!+9#!}56#sqGDbFOF_szGSR3fOS}Cpmst>J8 z^ERa`VG7W5!`770n${DVw<%o-(~psPDWSgC6PoEMT?vd=WO}VBp}yA>pd-ty^m;<` zHl-^8<>Z^HnP6+z6PmXvT?uG7-)$+OzSk3(&zZiC9Ccpj&_SL|lu+O9V~MfApIRxM zdDrX%YRMCpS}9$9sFl*0Ma@2-uRJNLmC|*rOc};aqpj_ce`-y&Ra&oFDP0LwGUx}j z3mU__*V-y508j2}rF8Y7R!T!-c!yklKr?s)p;k&)A8MsEw1jVdst;&J+^W>OX{FZ_ z&<|!c>wQ2o;&!OMOH<#~hZ4|_$h9h62`En7a@F@ZT2m#kMxMTeo3u)3P3wuE<6cZ# zSP5tbTct#l!}odu`oW$nT?uFgM^_2;y`F%6a0ZpG1hj-vqJ;Xc1T=#Yr!*9UF|Q~aS` zo~l*t;DZ@wZIxwY{XFP7)v!{!653lG1#Mw%m3p839i7AJ_~^K)zuGF)D;et;QT0~| z9e1VGUu##{ySpd)cNsY!JKGs!eseb>Q3fho(Wq7v){oq|z zKF2&KVRtXX%6I)v*WAb64_T zw%^p>ZDZDWdxps8{Z*FXBMGZltd!QWf4ze*IsD9tSmIq@T1E84bNJ}rei#uE$5tgB zF~;X@X)|~o=NvW2Jdbh9=O`uNaW%$At?KC7JNofWk*?ZQiMSo4ipHC2el4O_N^7~b z)Ak*}ulsiZMvS)rW;M>ZT2`XIA5c2W=w1Js%ICx8V7vv;IL_yls8Ov}NrU)>#noH= zTZ1|#m~*}*&2lAFKPsJL2*UJgMZJP|zUM-#=p&ySuuLM}L2yr1tEAyW_bF4+ewR_- zfa5u}eGp5;uKqI9+@pL3H)GDDx4d0OWbi$Amf^voq!YRiRvKf)np(SPcb32PZ;Ikg z6?aZ+Ro@5et+NukTUNTZ>K4=XFZ6F9p|5;@3RRQ$oFn6G%Ov#8ap*2Hz@*W0BR1#* zIwqkT-qtA#Q)7?iWsukKUkvNoSsHornDX&C5_<;VJ~FC9QK?<|+?wj&az?Av%Ih6xL)9)PHkg+n!kJ&8Ror*;ImQFuaxyPT zt7yCAD4hmj8Ne!X23P8_e_%~eakQ*NtPfg2Yhw?u?}UB-SjGNfGd0#-Rqd+Ow&Qf7 zS}C1n^uyNRD%POhvBoaSbIqYu+lgw0RTL|@YCgR1jd<19T&eM#>wgd^;O4h0!(lpB G@c#h1;8NcJ diff --git a/files/beam-square.stl b/files/beam-square.stl deleted file mode 100644 index 011725b2e0bc104a14f4972db20028474b628db8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 684 zcmbtRF%E+;5X+4Ei2kHPbm&rbU}c02wSB_PU3d~-BaU<21&|mT3F7!{=aRg>!@F(j z`}O(hhp`I(jtc`MPdCin^sDiO@Mv@mY&_NYOLTaZcT>eA=a>xxF_#>Z*18Z$ba>TT zPv9&cqOwCU-i7=iM=B_lC+3Nv#_+km!}6|hM> Date: Tue, 11 Jul 2023 17:29:36 +0330 Subject: [PATCH 547/775] Benchmark cases --- examples/finite_elements/main.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 79cd842f7..f75f7bd34 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -68,9 +68,29 @@ func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shap return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3, restraint, load) } +// Declare the enum using iota and const +type Benchmark int + +const ( + Square Benchmark = iota + 1 + Circle + Pipe + I + Unknown +) + // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - benchmarkSquare() + benchmark := Square + + switch benchmark { + case Square: + benchmarkSquare() + case Circle: + case Pipe: + case I: + default: + } } From e0e8d5b1e2d54c16256a8f0eee470538d6c0b6fe Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 11 Jul 2023 17:30:19 +0330 Subject: [PATCH 548/775] Relocate code --- examples/finite_elements/main.go | 54 ++++++++++++++++---------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f75f7bd34..f571dac4c 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -17,6 +17,33 @@ import ( "github.com/deadsy/sdfx/sdf" ) +// Declare the enum using iota and const +type Benchmark int + +const ( + Square Benchmark = iota + 1 + Circle + Pipe + I + Unknown +) + +// Render SDF3 to finite elements. +// Write finite elements to an `inp` file. +// Written file can be used by ABAQUS or CalculiX. +func main() { + benchmark := Square + + switch benchmark { + case Square: + benchmarkSquare() + case Circle: + case Pipe: + case I: + default: + } +} + // By dilating SDF a little bit we may actually get rid of // bad elements like disconnected or improperly connected elements. // Erode so that SDF returns to its original size, well almost. @@ -67,30 +94,3 @@ func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shap // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3, restraint, load) } - -// Declare the enum using iota and const -type Benchmark int - -const ( - Square Benchmark = iota + 1 - Circle - Pipe - I - Unknown -) - -// Render SDF3 to finite elements. -// Write finite elements to an `inp` file. -// Written file can be used by ABAQUS or CalculiX. -func main() { - benchmark := Square - - switch benchmark { - case Square: - benchmarkSquare() - case Circle: - case Pipe: - case I: - default: - } -} From dca95ad8ff7e18d9046e9dc188310130f7094807 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 11 Jul 2023 17:30:44 +0330 Subject: [PATCH 549/775] Relocate code --- examples/finite_elements/main.go | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f571dac4c..1425c2664 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -44,26 +44,6 @@ func main() { } } -// By dilating SDF a little bit we may actually get rid of -// bad elements like disconnected or improperly connected elements. -// Erode so that SDF returns to its original size, well almost. -func dilationErosion(s sdf.SDF3) sdf.SDF3 { - min := s.BoundingBox().Min - max := s.BoundingBox().Max - - dimX := (max.X - min.X) - dimY := (max.Y - min.Y) - dimZ := (max.Z - min.Z) - - // What percent is preferred? Calibration is done a bit. - factor := math.Min(dimX, math.Min(dimY, dimZ)) * float64(0.02) - - dilation := sdf.Offset3D(s, factor) - erosion := sdf.Offset3D(dilation, -factor) - - return erosion -} - // Generate finite elements. func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, restraint func(x, y, z float64) (bool, bool, bool), @@ -94,3 +74,23 @@ func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shap // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3, restraint, load) } + +// By dilating SDF a little bit we may actually get rid of +// bad elements like disconnected or improperly connected elements. +// Erode so that SDF returns to its original size, well almost. +func dilationErosion(s sdf.SDF3) sdf.SDF3 { + min := s.BoundingBox().Min + max := s.BoundingBox().Max + + dimX := (max.X - min.X) + dimY := (max.Y - min.Y) + dimZ := (max.Z - min.Z) + + // What percent is preferred? Calibration is done a bit. + factor := math.Min(dimX, math.Min(dimY, dimZ)) * float64(0.02) + + dilation := sdf.Offset3D(s, factor) + erosion := sdf.Offset3D(dilation, -factor) + + return erosion +} From 0ec770e1299f5c101b79acbffeae53de820f004b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 11 Jul 2023 17:32:41 +0330 Subject: [PATCH 550/775] Comment --- examples/finite_elements/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 1425c2664..019f80a9d 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -31,6 +31,8 @@ const ( // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. +// +// OpenSCAD must be installed and be available on PATH as `openscad` func main() { benchmark := Square From 01a9e95f01d0089d6af250c3fa16a6b8049ff8f6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 09:43:34 +0330 Subject: [PATCH 551/775] Command line arg to specify benchmark to run --- examples/finite_elements/main.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 019f80a9d..a7c6f6958 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -10,7 +10,10 @@ Output `inp` file is consumable by ABAQUS or CalculiX. package main import ( + "log" "math" + "os" + "strconv" "github.com/deadsy/sdfx/render" "github.com/deadsy/sdfx/render/finiteelements/mesh" @@ -36,6 +39,15 @@ const ( func main() { benchmark := Square + // Optional argument from 1 to 4 to specify the benchmark to run. + if len(os.Args) > 1 { + bmint, err := strconv.Atoi(os.Args[1]) + if err != nil { + log.Fatalf("error: %s", err) + } + benchmark = Benchmark(bmint) + } + switch benchmark { case Square: benchmarkSquare() From f3e614de0b4175da09fad42f001f1b4e0e38e484 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 10:15:00 +0330 Subject: [PATCH 552/775] Single responsibility --- examples/finite_elements/benchmark-squre.go | 118 +------------------- examples/finite_elements/main.go | 110 +++++++++++++++++- 2 files changed, 111 insertions(+), 117 deletions(-) diff --git a/examples/finite_elements/benchmark-squre.go b/examples/finite_elements/benchmark-squre.go index 8397c56ac..ab7660dc9 100644 --- a/examples/finite_elements/benchmark-squre.go +++ b/examples/finite_elements/benchmark-squre.go @@ -1,123 +1,9 @@ package main -import ( - "fmt" - "log" - "os" - "os/exec" - - "github.com/deadsy/sdfx/obj" - "github.com/deadsy/sdfx/render" -) - -func bmSquareRestraint(x, y, z float64) (bool, bool, bool) { +func restraintSquare(x, y, z float64) (bool, bool, bool) { return false, false, false } -func bmSquareLoad(x, y, z float64) (float64, float64, float64) { +func loadSquare(x, y, z float64) (float64, float64, float64) { return 0, 0, 0 } - -// Benchmark reference: -// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections -func benchmarkSquare() { - prg := "openscad" - - arg1 := "-o" - arg2_stl := "3d-beam-square.stl" - arg3_cad := "../../files/beam-square.scad" - - cmd := exec.Command(prg, arg1, arg2_stl, arg3_cad) - stdout, err := cmd.Output() - - if err != nil { - log.Fatalf("error: %s", err) - return - } - - fmt.Println(string(stdout)) - - // read the stl file. - file, err := os.OpenFile(arg2_stl, os.O_RDONLY, 0400) - if err != nil { - log.Fatalf("error: %s", err) - } - - // create the SDF from the STL mesh - inSdf, err := obj.ImportSTL(file, 20, 3, 5) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet4 i.e. 4-node tetrahedron - err = fe(inSdf, 50, render.Linear, render.Tetrahedral, "tet4.inp", bmSquareRestraint, bmSquareLoad) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet4 i.e. 4-node tetrahedron - err = fePartial(inSdf, 50, render.Linear, render.Tetrahedral, "partial-tet4.inp", bmSquareRestraint, bmSquareLoad, 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet10 i.e. 10-node tetrahedron - err = fe(inSdf, 50, render.Quadratic, render.Tetrahedral, "tet10.inp", bmSquareRestraint, bmSquareLoad) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet10 i.e. 10-node tetrahedron - err = fePartial(inSdf, 50, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", bmSquareRestraint, bmSquareLoad, 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 i.e. 8-node hexahedron - err = fe(inSdf, 50, render.Linear, render.Hexahedral, "hex8.inp", bmSquareRestraint, bmSquareLoad) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 i.e. 8-node hexahedron - err = fePartial(inSdf, 50, render.Linear, render.Hexahedral, "partial-hex8.inp", bmSquareRestraint, bmSquareLoad, 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 i.e. 20-node hexahedron - err = fe(inSdf, 50, render.Quadratic, render.Hexahedral, "hex20.inp", bmSquareRestraint, bmSquareLoad) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 i.e. 20-node hexahedron - err = fePartial(inSdf, 50, render.Quadratic, render.Hexahedral, "partial-hex20.inp", bmSquareRestraint, bmSquareLoad, 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 and tet4 - err = fe(inSdf, 50, render.Linear, render.Both, "hex8tet4.inp", bmSquareRestraint, bmSquareLoad) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 and tet4 - err = fePartial(inSdf, 50, render.Linear, render.Both, "partial-hex8tet4.inp", bmSquareRestraint, bmSquareLoad, 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 and tet10 - err = fe(inSdf, 50, render.Quadratic, render.Both, "hex20tet10.inp", bmSquareRestraint, bmSquareLoad) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 and tet10 - err = fePartial(inSdf, 50, render.Quadratic, render.Both, "partial-hex20tet10.inp", bmSquareRestraint, bmSquareLoad, 0, 3) - if err != nil { - log.Fatalf("error: %s", err) - } -} diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index a7c6f6958..2294b0d00 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -10,11 +10,14 @@ Output `inp` file is consumable by ABAQUS or CalculiX. package main import ( + "fmt" "log" "math" "os" + "os/exec" "strconv" + "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" "github.com/deadsy/sdfx/render/finiteelements/mesh" "github.com/deadsy/sdfx/sdf" @@ -50,7 +53,7 @@ func main() { switch benchmark { case Square: - benchmarkSquare() + benchmarkRun("../../files/beam-square.scad", 50, 0, 3, restraintSquare, loadSquare) case Circle: case Pipe: case I: @@ -58,6 +61,111 @@ func main() { } } +// Benchmark reference: +// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections +func benchmarkRun( + cad string, + resolution int, + layerStart, layerEnd int, + restraint func(x, y, z float64) (bool, bool, bool), + load func(x, y, z float64) (float64, float64, float64), +) { + prg := "openscad" + stl := "3d-beam.stl" + cmd := exec.Command(prg, "-o", stl, cad) + stdout, err := cmd.Output() + if err != nil { + log.Fatalf("error: %s", err) + return + } + + fmt.Println(string(stdout)) + + // read the stl file. + file, err := os.OpenFile(stl, os.O_RDONLY, 0400) + if err != nil { + log.Fatalf("error: %s", err) + } + + // create the SDF from the STL mesh + inSdf, err := obj.ImportSTL(file, 20, 3, 5) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet4 i.e. 4-node tetrahedron + err = fe(inSdf, resolution, render.Linear, render.Tetrahedral, "tet4.inp", restraint, load) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet4 i.e. 4-node tetrahedron + err = fePartial(inSdf, resolution, render.Linear, render.Tetrahedral, "partial-tet4.inp", restraint, load, layerStart, layerEnd) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet10 i.e. 10-node tetrahedron + err = fe(inSdf, resolution, render.Quadratic, render.Tetrahedral, "tet10.inp", restraint, load) + if err != nil { + log.Fatalf("error: %s", err) + } + + // tet10 i.e. 10-node tetrahedron + err = fePartial(inSdf, resolution, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", restraint, load, layerStart, layerEnd) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 i.e. 8-node hexahedron + err = fe(inSdf, resolution, render.Linear, render.Hexahedral, "hex8.inp", restraint, load) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 i.e. 8-node hexahedron + err = fePartial(inSdf, resolution, render.Linear, render.Hexahedral, "partial-hex8.inp", restraint, load, layerStart, layerEnd) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 i.e. 20-node hexahedron + err = fe(inSdf, resolution, render.Quadratic, render.Hexahedral, "hex20.inp", restraint, load) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 i.e. 20-node hexahedron + err = fePartial(inSdf, resolution, render.Quadratic, render.Hexahedral, "partial-hex20.inp", restraint, load, layerStart, layerEnd) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 and tet4 + err = fe(inSdf, resolution, render.Linear, render.Both, "hex8tet4.inp", restraint, load) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex8 and tet4 + err = fePartial(inSdf, resolution, render.Linear, render.Both, "partial-hex8tet4.inp", restraint, load, layerStart, layerEnd) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 and tet10 + err = fe(inSdf, resolution, render.Quadratic, render.Both, "hex20tet10.inp", restraint, load) + if err != nil { + log.Fatalf("error: %s", err) + } + + // hex20 and tet10 + err = fePartial(inSdf, resolution, render.Quadratic, render.Both, "partial-hex20tet10.inp", restraint, load, layerStart, layerEnd) + if err != nil { + log.Fatalf("error: %s", err) + } +} + // Generate finite elements. func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, restraint func(x, y, z float64) (bool, bool, bool), From 5388066a88702125a81366df61c5b142bd0b30c6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 10:26:12 +0330 Subject: [PATCH 553/775] Clear file names --- examples/finite_elements/main.go | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 2294b0d00..a3112a9b0 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -100,7 +100,11 @@ func benchmarkRun( } // tet4 i.e. 4-node tetrahedron - err = fePartial(inSdf, resolution, render.Linear, render.Tetrahedral, "partial-tet4.inp", restraint, load, layerStart, layerEnd) + err = fePartial( + inSdf, resolution, render.Linear, render.Tetrahedral, + fmt.Sprintf("tet4--layers-%v-to-%v.inp", layerStart, layerEnd), + restraint, load, layerStart, layerEnd, + ) if err != nil { log.Fatalf("error: %s", err) } @@ -112,7 +116,11 @@ func benchmarkRun( } // tet10 i.e. 10-node tetrahedron - err = fePartial(inSdf, resolution, render.Quadratic, render.Tetrahedral, "partial-tet10.inp", restraint, load, layerStart, layerEnd) + err = fePartial( + inSdf, resolution, render.Quadratic, render.Tetrahedral, + fmt.Sprintf("tet10--layers-%v-to-%v.inp", layerStart, layerEnd), + restraint, load, layerStart, layerEnd, + ) if err != nil { log.Fatalf("error: %s", err) } @@ -124,7 +132,10 @@ func benchmarkRun( } // hex8 i.e. 8-node hexahedron - err = fePartial(inSdf, resolution, render.Linear, render.Hexahedral, "partial-hex8.inp", restraint, load, layerStart, layerEnd) + err = fePartial(inSdf, resolution, render.Linear, render.Hexahedral, + fmt.Sprintf("hex8--layers-%v-to-%v.inp", layerStart, layerEnd), + restraint, load, layerStart, layerEnd, + ) if err != nil { log.Fatalf("error: %s", err) } @@ -136,7 +147,10 @@ func benchmarkRun( } // hex20 i.e. 20-node hexahedron - err = fePartial(inSdf, resolution, render.Quadratic, render.Hexahedral, "partial-hex20.inp", restraint, load, layerStart, layerEnd) + err = fePartial(inSdf, resolution, render.Quadratic, render.Hexahedral, + fmt.Sprintf("hex20--layers-%v-to-%v.inp", layerStart, layerEnd), + restraint, load, layerStart, layerEnd, + ) if err != nil { log.Fatalf("error: %s", err) } @@ -148,7 +162,10 @@ func benchmarkRun( } // hex8 and tet4 - err = fePartial(inSdf, resolution, render.Linear, render.Both, "partial-hex8tet4.inp", restraint, load, layerStart, layerEnd) + err = fePartial(inSdf, resolution, render.Linear, render.Both, + fmt.Sprintf("hex8tet4--layers-%v-to-%v.inp", layerStart, layerEnd), + restraint, load, layerStart, layerEnd, + ) if err != nil { log.Fatalf("error: %s", err) } @@ -160,7 +177,10 @@ func benchmarkRun( } // hex20 and tet10 - err = fePartial(inSdf, resolution, render.Quadratic, render.Both, "partial-hex20tet10.inp", restraint, load, layerStart, layerEnd) + err = fePartial(inSdf, resolution, render.Quadratic, render.Both, + fmt.Sprintf("hex20tet10--layers-%v-to-%v.inp", layerStart, layerEnd), + restraint, load, layerStart, layerEnd, + ) if err != nil { log.Fatalf("error: %s", err) } From 2c36e22fe555361de7c15023d9c7c57a7e12f63e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 10:35:17 +0330 Subject: [PATCH 554/775] Rename files --- examples/finite_elements/main.go | 4 ++-- files/{beam-I.scad => benchmark-I.scad} | 0 files/{beam-circle.scad => benchmark-circle.scad} | 0 files/{beam-pipe.scad => benchmark-pipe.scad} | 0 files/{beam-square.scad => benchmark-square.scad} | 0 5 files changed, 2 insertions(+), 2 deletions(-) rename files/{beam-I.scad => benchmark-I.scad} (100%) rename files/{beam-circle.scad => benchmark-circle.scad} (100%) rename files/{beam-pipe.scad => benchmark-pipe.scad} (100%) rename files/{beam-square.scad => benchmark-square.scad} (100%) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index a3112a9b0..19244455e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -53,7 +53,7 @@ func main() { switch benchmark { case Square: - benchmarkRun("../../files/beam-square.scad", 50, 0, 3, restraintSquare, loadSquare) + benchmarkRun("../../files/benchmark-square.scad", 50, 0, 3, restraintSquare, loadSquare) case Circle: case Pipe: case I: @@ -71,7 +71,7 @@ func benchmarkRun( load func(x, y, z float64) (float64, float64, float64), ) { prg := "openscad" - stl := "3d-beam.stl" + stl := "benchmark.stl" cmd := exec.Command(prg, "-o", stl, cad) stdout, err := cmd.Output() if err != nil { diff --git a/files/beam-I.scad b/files/benchmark-I.scad similarity index 100% rename from files/beam-I.scad rename to files/benchmark-I.scad diff --git a/files/beam-circle.scad b/files/benchmark-circle.scad similarity index 100% rename from files/beam-circle.scad rename to files/benchmark-circle.scad diff --git a/files/beam-pipe.scad b/files/benchmark-pipe.scad similarity index 100% rename from files/beam-pipe.scad rename to files/benchmark-pipe.scad diff --git a/files/beam-square.scad b/files/benchmark-square.scad similarity index 100% rename from files/beam-square.scad rename to files/benchmark-square.scad From 944dcb59737c1f82202935e05a2611e370e6f2fe Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 11:07:47 +0330 Subject: [PATCH 555/775] Remove outdated parameter --- examples/finite_elements/main.go | 4 ++-- render/finiteelements/mesh/fem.go | 6 ++---- render/finiteelements/mesh/inp.go | 4 ---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 19244455e..ea5a02097 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -197,7 +197,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write all layers of mesh to file. - return m.WriteInp(pth, []int{0, 1, 2}, 1.25e-9, 900, 0.3, restraint, load) + return m.WriteInp(pth, 1.25e-9, 900, 0.3, restraint, load) } // Generate finite elements. @@ -214,7 +214,7 @@ func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shap m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to file. - return m.WriteInpLayers(pth, layerStart, layerEnd, []int{0, 1, 2}, 1.25e-9, 900, 0.3, restraint, load) + return m.WriteInpLayers(pth, layerStart, layerEnd, 1.25e-9, 900, 0.3, restraint, load) } // By dilating SDF a little bit we may actually get rid of diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 924cae7ba..03188139a 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -79,7 +79,6 @@ func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. func (m *Fem) WriteInp( path string, - layersFixed []int, massDensity float32, youngModulus float32, poissonRatio float32, @@ -87,7 +86,7 @@ func (m *Fem) WriteInp( load func(x, y, z float64) (float64, float64, float64), ) error { _, _, layersZ := m.IBuff.Size() - return m.WriteInpLayers(path, 0, layersZ, layersFixed, massDensity, youngModulus, poissonRatio, restraint, load) + return m.WriteInpLayers(path, 0, layersZ, massDensity, youngModulus, poissonRatio, restraint, load) } // WriteInpLayers writes specific layers of mesh to ABAQUS or CalculiX `inp` file. @@ -96,14 +95,13 @@ func (m *Fem) WriteInp( func (m *Fem) WriteInpLayers( path string, layerStart, layerEnd int, - layersFixed []int, massDensity float32, youngModulus float32, poissonRatio float32, restraint func(x, y, z float64) (bool, bool, bool), load func(x, y, z float64) (float64, float64, float64), ) error { - inp := NewInp(m, path, layerStart, layerEnd, layersFixed, massDensity, youngModulus, poissonRatio, restraint, load) + inp := NewInp(m, path, layerStart, layerEnd, massDensity, youngModulus, poissonRatio, restraint, load) return inp.Write() } diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 35a4480c7..1a0104443 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -31,8 +31,6 @@ type Inp struct { LayerStart int // Output `inp` file would exclude end layer. LayerEnd int - // Layers fixed to the 3D print floor i.e. bottom layers. The boundary conditions. - LayersFixed []int // To write only required nodes to `inp` file. TempVBuff *buffer.VB // Mechanical properties of 3D print resin. @@ -56,7 +54,6 @@ func NewInp( m *Fem, path string, layerStart, layerEnd int, - layersFixed []int, massDensity float32, youngModulus float32, poissonRatio float32, restraint func(x, y, z float64) (bool, bool, bool), load func(x, y, z float64) (float64, float64, float64), @@ -72,7 +69,6 @@ func NewInp( PathBou: path + ".boundary", LayerStart: layerStart, LayerEnd: layerEnd, - LayersFixed: layersFixed, TempVBuff: buffer.NewVB(), MassDensity: massDensity, YoungModulus: youngModulus, From 340376720a8c37641ea62fef9b6b882ca6728cbc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 11:09:08 +0330 Subject: [PATCH 556/775] Rename func --- examples/finite_elements/main.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index ea5a02097..75231ab4c 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -100,7 +100,7 @@ func benchmarkRun( } // tet4 i.e. 4-node tetrahedron - err = fePartial( + err = feLayers( inSdf, resolution, render.Linear, render.Tetrahedral, fmt.Sprintf("tet4--layers-%v-to-%v.inp", layerStart, layerEnd), restraint, load, layerStart, layerEnd, @@ -116,7 +116,7 @@ func benchmarkRun( } // tet10 i.e. 10-node tetrahedron - err = fePartial( + err = feLayers( inSdf, resolution, render.Quadratic, render.Tetrahedral, fmt.Sprintf("tet10--layers-%v-to-%v.inp", layerStart, layerEnd), restraint, load, layerStart, layerEnd, @@ -132,7 +132,7 @@ func benchmarkRun( } // hex8 i.e. 8-node hexahedron - err = fePartial(inSdf, resolution, render.Linear, render.Hexahedral, + err = feLayers(inSdf, resolution, render.Linear, render.Hexahedral, fmt.Sprintf("hex8--layers-%v-to-%v.inp", layerStart, layerEnd), restraint, load, layerStart, layerEnd, ) @@ -147,7 +147,7 @@ func benchmarkRun( } // hex20 i.e. 20-node hexahedron - err = fePartial(inSdf, resolution, render.Quadratic, render.Hexahedral, + err = feLayers(inSdf, resolution, render.Quadratic, render.Hexahedral, fmt.Sprintf("hex20--layers-%v-to-%v.inp", layerStart, layerEnd), restraint, load, layerStart, layerEnd, ) @@ -162,7 +162,7 @@ func benchmarkRun( } // hex8 and tet4 - err = fePartial(inSdf, resolution, render.Linear, render.Both, + err = feLayers(inSdf, resolution, render.Linear, render.Both, fmt.Sprintf("hex8tet4--layers-%v-to-%v.inp", layerStart, layerEnd), restraint, load, layerStart, layerEnd, ) @@ -177,7 +177,7 @@ func benchmarkRun( } // hex20 and tet10 - err = fePartial(inSdf, resolution, render.Quadratic, render.Both, + err = feLayers(inSdf, resolution, render.Quadratic, render.Both, fmt.Sprintf("hex20tet10--layers-%v-to-%v.inp", layerStart, layerEnd), restraint, load, layerStart, layerEnd, ) @@ -203,7 +203,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth // Generate finite elements. // Only from a start layer to an end layer along the Z axis. // Applicable to 3D print analysis that is done layer-by-layer. -func fePartial(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, +func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, restraint func(x, y, z float64) (bool, bool, bool), load func(x, y, z float64) (float64, float64, float64), layerStart, layerEnd int, From f4fac53861756567658d196792aff5aaf8dc8118 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 13:02:19 +0330 Subject: [PATCH 557/775] Write custom restraints --- render/finiteelements/mesh/inp.go | 70 ++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 1a0104443..72f07483e 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -350,17 +350,6 @@ func (inp *Inp) writeBoundary() error { inp.nextNodeBou = 1 // ID starts from one not zero. process = func(x, y, z int, els []*buffer.Element) { - var isLayerFixed bool - for _, l := range inp.LayersFixed { - if l == z { - isLayerFixed = true - } - } - - if !isLayerFixed { - return - } - for _, el := range els { vertices := make([]v3.Vec, len(el.Nodes)) ids := make([]uint32, len(el.Nodes)) @@ -371,12 +360,63 @@ func (inp *Inp) writeBoundary() error { // Write the node IDs. for n := 0; n < len(el.Nodes); n++ { + vertex := vertices[n] + isFixedX, isFixedY, isFixedZ := inp.Restraint(vertex.X, vertex.Y, vertex.Z) + if !isFixedX && !isFixedY && !isFixedZ { + continue + } + + // ID starts from one not zero. + // Only write node if it's not already written to file. if ids[n]+1 == inp.nextNodeBou { - // ID starts from one not zero. - _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) + + // To be written: + // 1) Node number/ID. + // 2) First degree of freedom constrained. + // 3) Last degree of freedom constrained. This field may be left blank if only + // one degree of freedom is constrained. + + if isFixedX && isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1,2\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,2,3\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && !isFixedY && isFixedZ { + // TODO: Can we write this case by just one line, not two lines? + _, err = f.WriteString(fmt.Sprintf("%d,1\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,3\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && !isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,2\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && !isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,3\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } } inp.nextNodeBou++ } From 2e9859af641b1cfbfd16c8d192261765964e523a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 13:38:38 +0330 Subject: [PATCH 558/775] Gravity direction and magnitude --- examples/finite_elements/main.go | 5 +- render/finiteelements/mesh/fem.go | 8 +++- render/finiteelements/mesh/inp.go | 78 ++++++++++++++++++++++--------- 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 75231ab4c..f8e39c01a 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -21,6 +21,7 @@ import ( "github.com/deadsy/sdfx/render" "github.com/deadsy/sdfx/render/finiteelements/mesh" "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" ) // Declare the enum using iota and const @@ -197,7 +198,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write all layers of mesh to file. - return m.WriteInp(pth, 1.25e-9, 900, 0.3, restraint, load) + return m.WriteInp(pth, 1.25e-9, 900, 0.3, restraint, load, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) } // Generate finite elements. @@ -214,7 +215,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to file. - return m.WriteInpLayers(pth, layerStart, layerEnd, 1.25e-9, 900, 0.3, restraint, load) + return m.WriteInpLayers(pth, layerStart, layerEnd, 1.25e-9, 900, 0.3, restraint, load, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) } // By dilating SDF a little bit we may actually get rid of diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 03188139a..a159abe7d 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -84,9 +84,11 @@ func (m *Fem) WriteInp( poissonRatio float32, restraint func(x, y, z float64) (bool, bool, bool), load func(x, y, z float64) (float64, float64, float64), + gravityDirection v3.Vec, + gravityMagnitude float64, ) error { _, _, layersZ := m.IBuff.Size() - return m.WriteInpLayers(path, 0, layersZ, massDensity, youngModulus, poissonRatio, restraint, load) + return m.WriteInpLayers(path, 0, layersZ, massDensity, youngModulus, poissonRatio, restraint, load, gravityDirection, gravityMagnitude) } // WriteInpLayers writes specific layers of mesh to ABAQUS or CalculiX `inp` file. @@ -100,8 +102,10 @@ func (m *Fem) WriteInpLayers( poissonRatio float32, restraint func(x, y, z float64) (bool, bool, bool), load func(x, y, z float64) (float64, float64, float64), + gravityDirection v3.Vec, + gravityMagnitude float64, ) error { - inp := NewInp(m, path, layerStart, layerEnd, massDensity, youngModulus, poissonRatio, restraint, load) + inp := NewInp(m, path, layerStart, layerEnd, massDensity, youngModulus, poissonRatio, restraint, load, gravityDirection, gravityMagnitude) return inp.Write() } diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 72f07483e..9a56ec500 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -47,6 +47,10 @@ type Inp struct { Restraint func(x, y, z float64) (bool, bool, bool) // Inside the function, according to the x, y, z, the caller decides on load. Load func(x, y, z float64) (float64, float64, float64) + // Assigns gravity loading in this direction to all elements. + GravityDirection v3.Vec + // Assigns gravity loading with magnitude to all elements. + GravityMagnitude float64 } // NewInp sets up a new writer. @@ -57,24 +61,28 @@ func NewInp( massDensity float32, youngModulus float32, poissonRatio float32, restraint func(x, y, z float64) (bool, bool, bool), load func(x, y, z float64) (float64, float64, float64), + gravityDirection v3.Vec, + gravityMagnitude float64, ) *Inp { return &Inp{ - Mesh: m, - Path: path, - PathNodes: path + ".nodes", - PathElsC3D4: path + ".elements_C3D4", - PathElsC3D10: path + ".elements_C3D10", - PathElsC3D8: path + ".elements_C3D8", - PathElsC3D20R: path + ".elements_C3D20R", - PathBou: path + ".boundary", - LayerStart: layerStart, - LayerEnd: layerEnd, - TempVBuff: buffer.NewVB(), - MassDensity: massDensity, - YoungModulus: youngModulus, - PoissonRatio: poissonRatio, - Restraint: restraint, - Load: load, + Mesh: m, + Path: path, + PathNodes: path + ".nodes", + PathElsC3D4: path + ".elements_C3D4", + PathElsC3D10: path + ".elements_C3D10", + PathElsC3D8: path + ".elements_C3D8", + PathElsC3D20R: path + ".elements_C3D20R", + PathBou: path + ".boundary", + LayerStart: layerStart, + LayerEnd: layerEnd, + TempVBuff: buffer.NewVB(), + MassDensity: massDensity, + YoungModulus: youngModulus, + PoissonRatio: poissonRatio, + Restraint: restraint, + Load: load, + GravityDirection: gravityDirection, + GravityMagnitude: gravityMagnitude, } } @@ -492,27 +500,53 @@ func (inp *Inp) writeFooter(f *os.File) error { return err } - // Assign gravity loading in the "positive" z-direction with magnitude 9810 to all elements. + // Assign gravity loading in any direction with any magnitude to all elements. + // + // 9810 could be gravity magnitude in mm/sec^2 units. // // SLA 3D printing is done upside-down. 3D model is hanging from the print floor. - // That's why gravity is in "positive" z-direction. + // That's why gravity could be in "positive" z-direction. // Here ”gravity” really stands for any acceleration vector. // // Refer to CalculiX solver documentation: // http://www.dhondt.de/ccx_2.20.pdf - _, err = f.WriteString("eC3D4,GRAV,9810.,0.,0.,1.\n") + _, err = f.WriteString( + fmt.Sprintf( + "eC3D4,GRAV,%v,%v,%v,%v\n", + inp.GravityMagnitude, + inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, + ), + ) if err != nil { return err } - _, err = f.WriteString("e3D10,GRAV,9810.,0.,0.,1.\n") + _, err = f.WriteString( + fmt.Sprintf( + "e3D10,GRAV,%v,%v,%v,%v\n", + inp.GravityMagnitude, + inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, + ), + ) if err != nil { return err } - _, err = f.WriteString("eC3D8,GRAV,9810.,0.,0.,1.\n") + _, err = f.WriteString( + fmt.Sprintf( + "eC3D8,GRAV,%v,%v,%v,%v\n", + inp.GravityMagnitude, + inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, + ), + ) if err != nil { return err } - _, err = f.WriteString("eC3D20R,GRAV,9810.,0.,0.,1.\n") + _, err = f.WriteString( + fmt.Sprintf( + "eC3D20R,GRAV,%v,%v,%v,%v\n", + inp.GravityMagnitude, + inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, + ), + ) if err != nil { return err } From 18012247fb2702c1fd64b146d01366ac5c338309 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 14:27:11 +0330 Subject: [PATCH 559/775] Restraint function for a benchmark: square --- examples/finite_elements/benchmark-squre.go | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/examples/finite_elements/benchmark-squre.go b/examples/finite_elements/benchmark-squre.go index ab7660dc9..82e719cfb 100644 --- a/examples/finite_elements/benchmark-squre.go +++ b/examples/finite_elements/benchmark-squre.go @@ -1,6 +1,28 @@ package main +import v3 "github.com/deadsy/sdfx/vec/v3" + +// The 3D beam is simply supported i.e. one end is pinned and the other end is roller. +// Benchmark reference: +// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections func restraintSquare(x, y, z float64) (bool, bool, bool) { + node := v3.Vec{X: x, Y: y, Z: z} + + // All three degrees of freedom are fixed. + if node.Equals(v3.Vec{X: 0, Y: 0, Z: 0}, 0.01) { + return true, true, true + } + if node.Equals(v3.Vec{X: 0, Y: 17.32, Z: 0}, 0.01) { + return true, true, true + } + + // Some degrees of freedom are fixed. + if node.Equals(v3.Vec{X: 200, Y: 0, Z: 0}, 0.01) { + return false, true, true + } + if node.Equals(v3.Vec{X: 200, Y: 17.32, Z: 0}, 0.01) { + return false, true, true + } return false, false, false } From bdc4dacbbca147fb2fb24277e7e121aafd54d208 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 14:32:01 +0330 Subject: [PATCH 560/775] Update material properties for benchmarks * Young's modulus * Density --- examples/finite_elements/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f8e39c01a..b84d5e3e0 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -198,7 +198,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write all layers of mesh to file. - return m.WriteInp(pth, 1.25e-9, 900, 0.3, restraint, load, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) + return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraint, load, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) } // Generate finite elements. @@ -215,7 +215,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to file. - return m.WriteInpLayers(pth, layerStart, layerEnd, 1.25e-9, 900, 0.3, restraint, load, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) + return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraint, load, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) } // By dilating SDF a little bit we may actually get rid of From eab15dd714a6dd7f129a06356479c1d21d098b3e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 14:41:02 +0330 Subject: [PATCH 561/775] Update read-me --- examples/finite_elements/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 31aabb3f4..487cd6a1f 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -40,7 +40,7 @@ zypper install cgx To visualize the `inp` file by CalculiX GraphiX: ```bash -cgx -c teapot-hex8.inp +cgx -c hex8.inp ``` # Analyze `inp` file @@ -48,21 +48,21 @@ cgx -c teapot-hex8.inp To run the `inp` files by FEA engines like CalculiX: ```bash -ccx -i teapot-hex8 +ccx -i hex8 ``` -The above `-i` flag expects a `teapot-hex8.inp` file. +The above `-i` flag expects a `hex8.inp` file. The above command creates `frd` files containing the results. They can be viewed by CalculiX GraphiX: ```bash -cgx teapot-hex8.frd +cgx hex8.frd ``` The boundary conditions and loads used in the calculation will be available together with the results if you run: ```bash -cgx teapot-hex8.frd teapot-hex8.inp +cgx hex8.frd hex8.inp ``` ## Math solver From 5452d2546bc84736e25642ed623b6ea00551c82e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 14:45:46 +0330 Subject: [PATCH 562/775] Comment --- examples/finite_elements/main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index b84d5e3e0..6ae0fbe83 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -40,6 +40,7 @@ const ( // Written file can be used by ABAQUS or CalculiX. // // OpenSCAD must be installed and be available on PATH as `openscad` +// https://openscad.org/downloads.html func main() { benchmark := Square @@ -64,6 +65,8 @@ func main() { // Benchmark reference: // https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections +// +// OpenSCAD must be installed on your system: https://openscad.org/downloads.html func benchmarkRun( cad string, resolution int, From b71f541f08a5605c30973cdb689866702a532544 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 14:58:35 +0330 Subject: [PATCH 563/775] Avoid OpenSCAD dependency, use STL instead --- examples/finite_elements/main.go | 21 +- files/benchmark-I.stl | 310 ++++++ files/benchmark-circle.stl | 814 +++++++++++++++ files/benchmark-pipe.stl | 1682 ++++++++++++++++++++++++++++++ files/benchmark-square.stl | 86 ++ 5 files changed, 2894 insertions(+), 19 deletions(-) create mode 100644 files/benchmark-I.stl create mode 100644 files/benchmark-circle.stl create mode 100644 files/benchmark-pipe.stl create mode 100644 files/benchmark-square.stl diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 6ae0fbe83..660efe7f1 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -14,7 +14,6 @@ import ( "log" "math" "os" - "os/exec" "strconv" "github.com/deadsy/sdfx/obj" @@ -38,9 +37,6 @@ const ( // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. -// -// OpenSCAD must be installed and be available on PATH as `openscad` -// https://openscad.org/downloads.html func main() { benchmark := Square @@ -55,7 +51,7 @@ func main() { switch benchmark { case Square: - benchmarkRun("../../files/benchmark-square.scad", 50, 0, 3, restraintSquare, loadSquare) + benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraintSquare, loadSquare) case Circle: case Pipe: case I: @@ -65,26 +61,13 @@ func main() { // Benchmark reference: // https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections -// -// OpenSCAD must be installed on your system: https://openscad.org/downloads.html func benchmarkRun( - cad string, + stl string, resolution int, layerStart, layerEnd int, restraint func(x, y, z float64) (bool, bool, bool), load func(x, y, z float64) (float64, float64, float64), ) { - prg := "openscad" - stl := "benchmark.stl" - cmd := exec.Command(prg, "-o", stl, cad) - stdout, err := cmd.Output() - if err != nil { - log.Fatalf("error: %s", err) - return - } - - fmt.Println(string(stdout)) - // read the stl file. file, err := os.OpenFile(stl, os.O_RDONLY, 0400) if err != nil { diff --git a/files/benchmark-I.stl b/files/benchmark-I.stl new file mode 100644 index 000000000..73169f864 --- /dev/null +++ b/files/benchmark-I.stl @@ -0,0 +1,310 @@ +solid OpenSCAD_Model + facet normal 1 0 0 + outer loop + vertex 200 25 33 + vertex 200 14.5 29 + vertex 200 25 29 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 14.5 29 + vertex 200 10.5 29 + vertex 200 14.5 4 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 25 33 + vertex 200 10.5 29 + vertex 200 14.5 29 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 0 33 + vertex 200 10.5 29 + vertex 200 25 33 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 10.5 29 + vertex 200 0 33 + vertex 200 0 29 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 14.5 4 + vertex 200 25 0 + vertex 200 25 4 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 10.5 4 + vertex 200 14.5 4 + vertex 200 10.5 29 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 10.5 4 + vertex 200 25 0 + vertex 200 14.5 4 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 0 0 + vertex 200 10.5 4 + vertex 200 0 4 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 10.5 4 + vertex 200 0 0 + vertex 200 25 0 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex 0 25 33 + vertex 200 0 33 + vertex 200 25 33 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 200 0 33 + vertex 0 25 33 + vertex 0 0 33 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 0 14.5 29 + vertex 200 25 29 + vertex 200 14.5 29 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 200 25 29 + vertex 0 14.5 29 + vertex 0 25 29 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 0 0 29 + vertex 200 10.5 29 + vertex 200 0 29 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 200 10.5 29 + vertex 0 0 29 + vertex 0 10.5 29 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 25 0 + vertex 0 14.5 4 + vertex 0 25 4 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 14.5 4 + vertex 0 10.5 4 + vertex 0 14.5 29 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 25 0 + vertex 0 10.5 4 + vertex 0 14.5 4 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 0 + vertex 0 10.5 4 + vertex 0 25 0 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 10.5 4 + vertex 0 0 0 + vertex 0 0 4 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 14.5 29 + vertex 0 25 33 + vertex 0 25 29 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 10.5 29 + vertex 0 14.5 29 + vertex 0 10.5 4 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 10.5 29 + vertex 0 25 33 + vertex 0 14.5 29 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 33 + vertex 0 10.5 29 + vertex 0 0 29 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 10.5 29 + vertex 0 0 33 + vertex 0 25 33 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 200 25 29 + vertex 0 25 33 + vertex 200 25 33 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 0 25 33 + vertex 200 25 29 + vertex 0 25 29 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 0 0 29 + vertex 200 0 33 + vertex 0 0 33 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 200 0 33 + vertex 0 0 29 + vertex 200 0 29 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex 0 25 4 + vertex 200 14.5 4 + vertex 200 25 4 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 200 14.5 4 + vertex 0 25 4 + vertex 0 14.5 4 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex 0 10.5 4 + vertex 200 0 4 + vertex 200 10.5 4 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 200 0 4 + vertex 0 10.5 4 + vertex 0 0 4 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 0 0 0 + vertex 200 25 0 + vertex 200 0 0 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 200 25 0 + vertex 0 0 0 + vertex 0 25 0 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 200 25 0 + vertex 0 25 4 + vertex 200 25 4 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 0 25 4 + vertex 200 25 0 + vertex 0 25 0 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 0 0 0 + vertex 200 0 4 + vertex 0 0 4 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 200 0 4 + vertex 0 0 0 + vertex 200 0 0 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 200 14.5 4 + vertex 0 14.5 29 + vertex 200 14.5 29 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 0 14.5 29 + vertex 200 14.5 4 + vertex 0 14.5 4 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 0 10.5 4 + vertex 200 10.5 29 + vertex 0 10.5 29 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 200 10.5 29 + vertex 0 10.5 4 + vertex 200 10.5 4 + endloop + endfacet +endsolid OpenSCAD_Model diff --git a/files/benchmark-circle.stl b/files/benchmark-circle.stl new file mode 100644 index 000000000..f5be69c2e --- /dev/null +++ b/files/benchmark-circle.stl @@ -0,0 +1,814 @@ +solid OpenSCAD_Model + facet normal 0 0.104528 -0.994522 + outer loop + vertex 0 0 0 + vertex 200 2.0313 0.213498 + vertex 200 0 0 + endloop + endfacet + facet normal 0 0.104528 -0.994522 + outer loop + vertex 200 2.0313 0.213498 + vertex 0 0 0 + vertex 0 2.0313 0.213498 + endloop + endfacet + facet normal 0 0.309017 -0.951057 + outer loop + vertex 0 2.0313 0.213498 + vertex 200 3.97382 0.844661 + vertex 200 2.0313 0.213498 + endloop + endfacet + facet normal 0 0.309017 -0.951057 + outer loop + vertex 200 3.97382 0.844661 + vertex 0 2.0313 0.213498 + vertex 0 3.97382 0.844661 + endloop + endfacet + facet normal 0 0.5 -0.866026 + outer loop + vertex 0 3.97382 0.844661 + vertex 200 5.74266 1.8659 + vertex 200 3.97382 0.844661 + endloop + endfacet + facet normal 0 0.5 -0.866026 + outer loop + vertex 200 5.74266 1.8659 + vertex 0 3.97382 0.844661 + vertex 0 5.74266 1.8659 + endloop + endfacet + facet normal 0 0.669131 -0.743144 + outer loop + vertex 0 5.74266 1.8659 + vertex 200 7.26052 3.23259 + vertex 200 5.74266 1.8659 + endloop + endfacet + facet normal 0 0.669131 -0.743144 + outer loop + vertex 200 7.26052 3.23259 + vertex 0 5.74266 1.8659 + vertex 0 7.26052 3.23259 + endloop + endfacet + facet normal 0 0.809016 -0.587786 + outer loop + vertex 200 7.26052 3.23259 + vertex 0 8.46107 4.885 + vertex 200 8.46107 4.885 + endloop + endfacet + facet normal 0 0.809016 -0.587786 + outer loop + vertex 0 8.46107 4.885 + vertex 200 7.26052 3.23259 + vertex 0 7.26052 3.23259 + endloop + endfacet + facet normal 0 0.913546 -0.406736 + outer loop + vertex 200 8.46107 4.885 + vertex 0 9.29182 6.7509 + vertex 200 9.29182 6.7509 + endloop + endfacet + facet normal 0 0.913546 -0.406736 + outer loop + vertex 0 9.29182 6.7509 + vertex 200 8.46107 4.885 + vertex 0 8.46107 4.885 + endloop + endfacet + facet normal 0 0.978147 -0.207913 + outer loop + vertex 200 9.29182 6.7509 + vertex 0 9.71648 8.74876 + vertex 200 9.71648 8.74876 + endloop + endfacet + facet normal 0 0.978147 -0.207913 + outer loop + vertex 0 9.71648 8.74876 + vertex 200 9.29182 6.7509 + vertex 0 9.29182 6.7509 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 200 9.71648 8.74876 + vertex 0 9.71648 10.7912 + vertex 200 9.71648 10.7912 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 0 9.71648 10.7912 + vertex 200 9.71648 8.74876 + vertex 0 9.71648 8.74876 + endloop + endfacet + facet normal 0 0.978148 0.207909 + outer loop + vertex 200 9.71648 10.7912 + vertex 0 9.29182 12.7891 + vertex 200 9.29182 12.7891 + endloop + endfacet + facet normal 0 0.978148 0.207909 + outer loop + vertex 0 9.29182 12.7891 + vertex 200 9.71648 10.7912 + vertex 0 9.71648 10.7912 + endloop + endfacet + facet normal 0 0.913546 0.406736 + outer loop + vertex 200 9.29182 12.7891 + vertex 0 8.46107 14.655 + vertex 200 8.46107 14.655 + endloop + endfacet + facet normal 0 0.913546 0.406736 + outer loop + vertex 0 8.46107 14.655 + vertex 200 9.29182 12.7891 + vertex 0 9.29182 12.7891 + endloop + endfacet + facet normal 0 0.809014 0.587789 + outer loop + vertex 200 8.46107 14.655 + vertex 0 7.26052 16.3074 + vertex 200 7.26052 16.3074 + endloop + endfacet + facet normal 0 0.809014 0.587789 + outer loop + vertex 0 7.26052 16.3074 + vertex 200 8.46107 14.655 + vertex 0 8.46107 14.655 + endloop + endfacet + facet normal -0 0.669134 0.743142 + outer loop + vertex 0 7.26052 16.3074 + vertex 200 5.74266 17.6741 + vertex 200 7.26052 16.3074 + endloop + endfacet + facet normal 0 0.669134 0.743142 + outer loop + vertex 200 5.74266 17.6741 + vertex 0 7.26052 16.3074 + vertex 0 5.74266 17.6741 + endloop + endfacet + facet normal -0 0.499985 0.866034 + outer loop + vertex 0 5.74266 17.6741 + vertex 200 3.97382 18.6953 + vertex 200 5.74266 17.6741 + endloop + endfacet + facet normal 0 0.499985 0.866034 + outer loop + vertex 200 3.97382 18.6953 + vertex 0 5.74266 17.6741 + vertex 0 3.97382 18.6953 + endloop + endfacet + facet normal -0 0.309033 0.951051 + outer loop + vertex 0 3.97382 18.6953 + vertex 200 2.0313 19.3265 + vertex 200 3.97382 18.6953 + endloop + endfacet + facet normal 0 0.309033 0.951051 + outer loop + vertex 200 2.0313 19.3265 + vertex 0 3.97382 18.6953 + vertex 0 2.0313 19.3265 + endloop + endfacet + facet normal -0 0.104529 0.994522 + outer loop + vertex 0 2.0313 19.3265 + vertex 200 0 19.54 + vertex 200 2.0313 19.3265 + endloop + endfacet + facet normal 0 0.104529 0.994522 + outer loop + vertex 200 0 19.54 + vertex 0 2.0313 19.3265 + vertex 0 0 19.54 + endloop + endfacet + facet normal 0 -0.104529 0.994522 + outer loop + vertex 0 0 19.54 + vertex 200 -2.0313 19.3265 + vertex 200 0 19.54 + endloop + endfacet + facet normal 0 -0.104529 0.994522 + outer loop + vertex 200 -2.0313 19.3265 + vertex 0 0 19.54 + vertex 0 -2.0313 19.3265 + endloop + endfacet + facet normal 0 -0.309033 0.951051 + outer loop + vertex 0 -2.0313 19.3265 + vertex 200 -3.97382 18.6953 + vertex 200 -2.0313 19.3265 + endloop + endfacet + facet normal 0 -0.309033 0.951051 + outer loop + vertex 200 -3.97382 18.6953 + vertex 0 -2.0313 19.3265 + vertex 0 -3.97382 18.6953 + endloop + endfacet + facet normal 0 -0.499985 0.866034 + outer loop + vertex 0 -3.97382 18.6953 + vertex 200 -5.74266 17.6741 + vertex 200 -3.97382 18.6953 + endloop + endfacet + facet normal 0 -0.499985 0.866034 + outer loop + vertex 200 -5.74266 17.6741 + vertex 0 -3.97382 18.6953 + vertex 0 -5.74266 17.6741 + endloop + endfacet + facet normal 0 -0.669134 0.743142 + outer loop + vertex 0 -5.74266 17.6741 + vertex 200 -7.26052 16.3074 + vertex 200 -5.74266 17.6741 + endloop + endfacet + facet normal 0 -0.669134 0.743142 + outer loop + vertex 200 -7.26052 16.3074 + vertex 0 -5.74266 17.6741 + vertex 0 -7.26052 16.3074 + endloop + endfacet + facet normal 0 -0.809014 0.587789 + outer loop + vertex 0 -8.46107 14.655 + vertex 200 -7.26052 16.3074 + vertex 0 -7.26052 16.3074 + endloop + endfacet + facet normal 0 -0.809014 0.587789 + outer loop + vertex 200 -7.26052 16.3074 + vertex 0 -8.46107 14.655 + vertex 200 -8.46107 14.655 + endloop + endfacet + facet normal 0 -0.913546 0.406736 + outer loop + vertex 0 -9.29182 12.7891 + vertex 200 -8.46107 14.655 + vertex 0 -8.46107 14.655 + endloop + endfacet + facet normal 0 -0.913546 0.406736 + outer loop + vertex 200 -8.46107 14.655 + vertex 0 -9.29182 12.7891 + vertex 200 -9.29182 12.7891 + endloop + endfacet + facet normal 0 -0.978148 0.207909 + outer loop + vertex 0 -9.71648 10.7912 + vertex 200 -9.29182 12.7891 + vertex 0 -9.29182 12.7891 + endloop + endfacet + facet normal 0 -0.978148 0.207909 + outer loop + vertex 200 -9.29182 12.7891 + vertex 0 -9.71648 10.7912 + vertex 200 -9.71648 10.7912 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 0 -9.71648 8.74876 + vertex 200 -9.71648 10.7912 + vertex 0 -9.71648 10.7912 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 200 -9.71648 10.7912 + vertex 0 -9.71648 8.74876 + vertex 200 -9.71648 8.74876 + endloop + endfacet + facet normal 0 -0.978147 -0.207913 + outer loop + vertex 0 -9.29182 6.7509 + vertex 200 -9.71648 8.74876 + vertex 0 -9.71648 8.74876 + endloop + endfacet + facet normal 0 -0.978147 -0.207913 + outer loop + vertex 200 -9.71648 8.74876 + vertex 0 -9.29182 6.7509 + vertex 200 -9.29182 6.7509 + endloop + endfacet + facet normal 0 -0.913546 -0.406736 + outer loop + vertex 0 -8.46107 4.885 + vertex 200 -9.29182 6.7509 + vertex 0 -9.29182 6.7509 + endloop + endfacet + facet normal 0 -0.913546 -0.406736 + outer loop + vertex 200 -9.29182 6.7509 + vertex 0 -8.46107 4.885 + vertex 200 -8.46107 4.885 + endloop + endfacet + facet normal 0 -0.809016 -0.587786 + outer loop + vertex 0 -7.26052 3.23259 + vertex 200 -8.46107 4.885 + vertex 0 -8.46107 4.885 + endloop + endfacet + facet normal 0 -0.809016 -0.587786 + outer loop + vertex 200 -8.46107 4.885 + vertex 0 -7.26052 3.23259 + vertex 200 -7.26052 3.23259 + endloop + endfacet + facet normal 0 -0.669131 -0.743144 + outer loop + vertex 0 -7.26052 3.23259 + vertex 200 -5.74266 1.8659 + vertex 200 -7.26052 3.23259 + endloop + endfacet + facet normal -0 -0.669131 -0.743144 + outer loop + vertex 200 -5.74266 1.8659 + vertex 0 -7.26052 3.23259 + vertex 0 -5.74266 1.8659 + endloop + endfacet + facet normal 0 -0.5 -0.866026 + outer loop + vertex 0 -5.74266 1.8659 + vertex 200 -3.97382 0.844661 + vertex 200 -5.74266 1.8659 + endloop + endfacet + facet normal -0 -0.5 -0.866026 + outer loop + vertex 200 -3.97382 0.844661 + vertex 0 -5.74266 1.8659 + vertex 0 -3.97382 0.844661 + endloop + endfacet + facet normal 0 -0.309017 -0.951057 + outer loop + vertex 0 -3.97382 0.844661 + vertex 200 -2.0313 0.213498 + vertex 200 -3.97382 0.844661 + endloop + endfacet + facet normal -0 -0.309017 -0.951057 + outer loop + vertex 200 -2.0313 0.213498 + vertex 0 -3.97382 0.844661 + vertex 0 -2.0313 0.213498 + endloop + endfacet + facet normal 0 -0.104528 -0.994522 + outer loop + vertex 0 -2.0313 0.213498 + vertex 200 0 0 + vertex 200 -2.0313 0.213498 + endloop + endfacet + facet normal -0 -0.104528 -0.994522 + outer loop + vertex 200 0 0 + vertex 0 -2.0313 0.213498 + vertex 0 0 0 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 9.29182 6.7509 + vertex 0 9.71648 10.7912 + vertex 0 9.71648 8.74876 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 9.29182 6.7509 + vertex 0 9.29182 12.7891 + vertex 0 9.71648 10.7912 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 8.46107 4.885 + vertex 0 9.29182 12.7891 + vertex 0 9.29182 6.7509 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 8.46107 4.885 + vertex 0 8.46107 14.655 + vertex 0 9.29182 12.7891 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 7.26052 3.23259 + vertex 0 8.46107 14.655 + vertex 0 8.46107 4.885 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 7.26052 3.23259 + vertex 0 7.26052 16.3074 + vertex 0 8.46107 14.655 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 5.74266 1.8659 + vertex 0 7.26052 16.3074 + vertex 0 7.26052 3.23259 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 5.74266 1.8659 + vertex 0 5.74266 17.6741 + vertex 0 7.26052 16.3074 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 3.97382 0.844661 + vertex 0 5.74266 17.6741 + vertex 0 5.74266 1.8659 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 3.97382 0.844661 + vertex 0 3.97382 18.6953 + vertex 0 5.74266 17.6741 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 2.0313 0.213498 + vertex 0 3.97382 18.6953 + vertex 0 3.97382 0.844661 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 2.0313 0.213498 + vertex 0 2.0313 19.3265 + vertex 0 3.97382 18.6953 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 0 + vertex 0 2.0313 19.3265 + vertex 0 2.0313 0.213498 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 0 + vertex 0 0 19.54 + vertex 0 2.0313 19.3265 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -2.0313 0.213498 + vertex 0 0 19.54 + vertex 0 0 0 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -2.0313 0.213498 + vertex 0 -2.0313 19.3265 + vertex 0 0 19.54 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -3.97382 0.844661 + vertex 0 -2.0313 19.3265 + vertex 0 -2.0313 0.213498 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -3.97382 0.844661 + vertex 0 -3.97382 18.6953 + vertex 0 -2.0313 19.3265 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -5.74266 1.8659 + vertex 0 -3.97382 18.6953 + vertex 0 -3.97382 0.844661 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -5.74266 1.8659 + vertex 0 -5.74266 17.6741 + vertex 0 -3.97382 18.6953 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -7.26052 3.23259 + vertex 0 -5.74266 17.6741 + vertex 0 -5.74266 1.8659 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -7.26052 3.23259 + vertex 0 -7.26052 16.3074 + vertex 0 -5.74266 17.6741 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -8.46107 4.885 + vertex 0 -7.26052 16.3074 + vertex 0 -7.26052 3.23259 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -8.46107 4.885 + vertex 0 -8.46107 14.655 + vertex 0 -7.26052 16.3074 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -9.29182 6.7509 + vertex 0 -8.46107 14.655 + vertex 0 -8.46107 4.885 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -9.29182 6.7509 + vertex 0 -9.29182 12.7891 + vertex 0 -8.46107 14.655 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -9.71648 8.74876 + vertex 0 -9.29182 12.7891 + vertex 0 -9.29182 6.7509 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -9.29182 12.7891 + vertex 0 -9.71648 8.74876 + vertex 0 -9.71648 10.7912 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 9.29182 12.7891 + vertex 200 9.71648 8.74876 + vertex 200 9.71648 10.7912 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 9.29182 12.7891 + vertex 200 9.29182 6.7509 + vertex 200 9.71648 8.74876 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 8.46107 14.655 + vertex 200 9.29182 6.7509 + vertex 200 9.29182 12.7891 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 8.46107 14.655 + vertex 200 8.46107 4.885 + vertex 200 9.29182 6.7509 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 7.26052 16.3074 + vertex 200 8.46107 4.885 + vertex 200 8.46107 14.655 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 7.26052 16.3074 + vertex 200 7.26052 3.23259 + vertex 200 8.46107 4.885 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 5.74266 17.6741 + vertex 200 7.26052 3.23259 + vertex 200 7.26052 16.3074 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 5.74266 17.6741 + vertex 200 5.74266 1.8659 + vertex 200 7.26052 3.23259 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 3.97382 18.6953 + vertex 200 5.74266 1.8659 + vertex 200 5.74266 17.6741 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 3.97382 18.6953 + vertex 200 3.97382 0.844661 + vertex 200 5.74266 1.8659 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 2.0313 19.3265 + vertex 200 3.97382 0.844661 + vertex 200 3.97382 18.6953 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 2.0313 19.3265 + vertex 200 2.0313 0.213498 + vertex 200 3.97382 0.844661 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 0 19.54 + vertex 200 2.0313 0.213498 + vertex 200 2.0313 19.3265 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 0 19.54 + vertex 200 0 0 + vertex 200 2.0313 0.213498 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -2.0313 19.3265 + vertex 200 0 0 + vertex 200 0 19.54 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -2.0313 19.3265 + vertex 200 -2.0313 0.213498 + vertex 200 0 0 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -3.97382 18.6953 + vertex 200 -2.0313 0.213498 + vertex 200 -2.0313 19.3265 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -3.97382 18.6953 + vertex 200 -3.97382 0.844661 + vertex 200 -2.0313 0.213498 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -5.74266 17.6741 + vertex 200 -3.97382 0.844661 + vertex 200 -3.97382 18.6953 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -5.74266 17.6741 + vertex 200 -5.74266 1.8659 + vertex 200 -3.97382 0.844661 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -7.26052 16.3074 + vertex 200 -5.74266 1.8659 + vertex 200 -5.74266 17.6741 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -7.26052 16.3074 + vertex 200 -7.26052 3.23259 + vertex 200 -5.74266 1.8659 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -8.46107 14.655 + vertex 200 -7.26052 3.23259 + vertex 200 -7.26052 16.3074 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -8.46107 14.655 + vertex 200 -8.46107 4.885 + vertex 200 -7.26052 3.23259 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -9.29182 12.7891 + vertex 200 -8.46107 4.885 + vertex 200 -8.46107 14.655 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -9.29182 12.7891 + vertex 200 -9.29182 6.7509 + vertex 200 -8.46107 4.885 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -9.71648 10.7912 + vertex 200 -9.29182 6.7509 + vertex 200 -9.29182 12.7891 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -9.29182 6.7509 + vertex 200 -9.71648 10.7912 + vertex 200 -9.71648 8.74876 + endloop + endfacet +endsolid OpenSCAD_Model diff --git a/files/benchmark-pipe.stl b/files/benchmark-pipe.stl new file mode 100644 index 000000000..a884a9324 --- /dev/null +++ b/files/benchmark-pipe.stl @@ -0,0 +1,1682 @@ +solid OpenSCAD_Model + facet normal -0 0.309008 0.951059 + outer loop + vertex 0 5.66787 26.6653 + vertex 200 2.89725 27.5655 + vertex 200 5.66787 26.6653 + endloop + endfacet + facet normal 0 0.309008 0.951059 + outer loop + vertex 200 2.89725 27.5655 + vertex 0 5.66787 26.6653 + vertex 0 2.89725 27.5655 + endloop + endfacet + facet normal 0 0.309016 -0.951057 + outer loop + vertex 0 2.89725 0.304514 + vertex 200 5.66787 1.20474 + vertex 200 2.89725 0.304514 + endloop + endfacet + facet normal 0 0.309016 -0.951057 + outer loop + vertex 200 5.66787 1.20474 + vertex 0 2.89725 0.304514 + vertex 0 5.66787 1.20474 + endloop + endfacet + facet normal 0 0.104529 -0.994522 + outer loop + vertex 0 0 5.34058e-07 + vertex 200 2.89725 0.304514 + vertex 200 0 5.34058e-07 + endloop + endfacet + facet normal 0 0.104529 -0.994522 + outer loop + vertex 200 2.89725 0.304514 + vertex 0 0 5.34058e-07 + vertex 0 2.89725 0.304514 + endloop + endfacet + facet normal 0 0.5 -0.866025 + outer loop + vertex 0 5.66787 1.20474 + vertex 200 8.19079 2.66135 + vertex 200 5.66787 1.20474 + endloop + endfacet + facet normal 0 0.5 -0.866025 + outer loop + vertex 200 8.19079 2.66135 + vertex 0 5.66787 1.20474 + vertex 0 8.19079 2.66135 + endloop + endfacet + facet normal 0 -0.669136 -0.74314 + outer loop + vertex 0 -10.3557 4.61067 + vertex 200 -8.19079 2.66135 + vertex 200 -10.3557 4.61067 + endloop + endfacet + facet normal -0 -0.669136 -0.74314 + outer loop + vertex 200 -8.19079 2.66135 + vertex 0 -10.3557 4.61067 + vertex 0 -8.19079 2.66135 + endloop + endfacet + facet normal 0 0.913547 -0.406734 + outer loop + vertex 200 12.0681 6.9675 + vertex 0 13.253 9.62885 + vertex 200 13.253 9.62885 + endloop + endfacet + facet normal 0 0.913547 -0.406734 + outer loop + vertex 0 13.253 9.62885 + vertex 200 12.0681 6.9675 + vertex 0 12.0681 6.9675 + endloop + endfacet + facet normal 0 -0.104529 -0.994522 + outer loop + vertex 0 -2.89725 0.304514 + vertex 200 0 5.34058e-07 + vertex 200 -2.89725 0.304514 + endloop + endfacet + facet normal -0 -0.104529 -0.994522 + outer loop + vertex 200 0 5.34058e-07 + vertex 0 -2.89725 0.304514 + vertex 0 0 5.34058e-07 + endloop + endfacet + facet normal 0 -0.5 -0.866025 + outer loop + vertex 0 -8.19079 2.66135 + vertex 200 -5.66787 1.20474 + vertex 200 -8.19079 2.66135 + endloop + endfacet + facet normal -0 -0.5 -0.866025 + outer loop + vertex 200 -5.66787 1.20474 + vertex 0 -8.19079 2.66135 + vertex 0 -5.66787 1.20474 + endloop + endfacet + facet normal -0 0.499998 0.866027 + outer loop + vertex 0 8.19079 25.2087 + vertex 200 5.66787 26.6653 + vertex 200 8.19079 25.2087 + endloop + endfacet + facet normal 0 0.499998 0.866027 + outer loop + vertex 200 5.66787 26.6653 + vertex 0 8.19079 25.2087 + vertex 0 5.66787 26.6653 + endloop + endfacet + facet normal 0 0.669136 -0.74314 + outer loop + vertex 0 8.19079 2.66135 + vertex 200 10.3557 4.61067 + vertex 200 8.19079 2.66135 + endloop + endfacet + facet normal 0 0.669136 -0.74314 + outer loop + vertex 200 10.3557 4.61067 + vertex 0 8.19079 2.66135 + vertex 0 10.3557 4.61067 + endloop + endfacet + facet normal 0 -0.499998 0.866027 + outer loop + vertex 0 -5.66787 26.6653 + vertex 200 -8.19079 25.2087 + vertex 200 -5.66787 26.6653 + endloop + endfacet + facet normal 0 -0.499998 0.866027 + outer loop + vertex 200 -8.19079 25.2087 + vertex 0 -5.66787 26.6653 + vertex 0 -8.19079 25.2087 + endloop + endfacet + facet normal 0 -0.913547 -0.406734 + outer loop + vertex 0 -12.0681 6.9675 + vertex 200 -13.253 9.62885 + vertex 0 -13.253 9.62885 + endloop + endfacet + facet normal 0 -0.913547 -0.406734 + outer loop + vertex 200 -13.253 9.62885 + vertex 0 -12.0681 6.9675 + vertex 200 -12.0681 6.9675 + endloop + endfacet + facet normal 0 -0.978148 0.207911 + outer loop + vertex 0 -13.8587 15.3916 + vertex 200 -13.253 18.2412 + vertex 0 -13.253 18.2412 + endloop + endfacet + facet normal 0 -0.978148 0.207911 + outer loop + vertex 200 -13.253 18.2412 + vertex 0 -13.8587 15.3916 + vertex 200 -13.8587 15.3916 + endloop + endfacet + facet normal -0 0.104524 0.994522 + outer loop + vertex 0 2.89725 27.5655 + vertex 200 0 27.87 + vertex 200 2.89725 27.5655 + endloop + endfacet + facet normal 0 0.104524 0.994522 + outer loop + vertex 200 0 27.87 + vertex 0 2.89725 27.5655 + vertex 0 0 27.87 + endloop + endfacet + facet normal 0 -0.309016 -0.951057 + outer loop + vertex 0 -5.66787 1.20474 + vertex 200 -2.89725 0.304514 + vertex 200 -5.66787 1.20474 + endloop + endfacet + facet normal -0 -0.309016 -0.951057 + outer loop + vertex 200 -2.89725 0.304514 + vertex 0 -5.66787 1.20474 + vertex 0 -2.89725 0.304514 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 200 13.8587 12.4784 + vertex 0 13.8587 15.3916 + vertex 200 13.8587 15.3916 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 0 13.8587 15.3916 + vertex 200 13.8587 12.4784 + vertex 0 13.8587 12.4784 + endloop + endfacet + facet normal 0 0.809003 0.587804 + outer loop + vertex 200 12.0681 20.9025 + vertex 0 10.3557 23.2593 + vertex 200 10.3557 23.2593 + endloop + endfacet + facet normal 0 0.809003 0.587804 + outer loop + vertex 0 10.3557 23.2593 + vertex 200 12.0681 20.9025 + vertex 0 12.0681 20.9025 + endloop + endfacet + facet normal 0 -0.913544 0.40674 + outer loop + vertex 0 -13.253 18.2412 + vertex 200 -12.0681 20.9025 + vertex 0 -12.0681 20.9025 + endloop + endfacet + facet normal 0 -0.913544 0.40674 + outer loop + vertex 200 -12.0681 20.9025 + vertex 0 -13.253 18.2412 + vertex 200 -13.253 18.2412 + endloop + endfacet + facet normal 0 -0.809007 -0.587799 + outer loop + vertex 0 -10.3557 4.61067 + vertex 200 -12.0681 6.9675 + vertex 0 -12.0681 6.9675 + endloop + endfacet + facet normal 0 -0.809007 -0.587799 + outer loop + vertex 200 -12.0681 6.9675 + vertex 0 -10.3557 4.61067 + vertex 200 -10.3557 4.61067 + endloop + endfacet + facet normal -0 0.669151 0.743127 + outer loop + vertex 0 10.3557 23.2593 + vertex 200 8.19079 25.2087 + vertex 200 10.3557 23.2593 + endloop + endfacet + facet normal 0 0.669151 0.743127 + outer loop + vertex 200 8.19079 25.2087 + vertex 0 10.3557 23.2593 + vertex 0 8.19079 25.2087 + endloop + endfacet + facet normal 0 0.913544 0.40674 + outer loop + vertex 200 13.253 18.2412 + vertex 0 12.0681 20.9025 + vertex 200 12.0681 20.9025 + endloop + endfacet + facet normal 0 0.913544 0.40674 + outer loop + vertex 0 12.0681 20.9025 + vertex 200 13.253 18.2412 + vertex 0 13.253 18.2412 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 9.88057 14.9735 + vertex 200 13.8587 15.3916 + vertex 200 13.253 18.2412 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 13.8587 15.3916 + vertex 200 9.88057 14.9735 + vertex 200 13.8587 12.4784 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 9.44875 17.0051 + vertex 200 13.253 18.2412 + vertex 200 12.0681 20.9025 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 9.88057 12.8965 + vertex 200 13.8587 12.4784 + vertex 200 9.88057 14.9735 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 8.60396 18.9025 + vertex 200 12.0681 20.9025 + vertex 200 10.3557 23.2593 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 13.8587 12.4784 + vertex 200 9.88057 12.8965 + vertex 200 13.253 9.62885 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 9.44875 10.8649 + vertex 200 13.253 9.62885 + vertex 200 9.88057 12.8965 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 13.253 18.2412 + vertex 200 9.44875 17.0051 + vertex 200 9.88057 14.9735 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 12.0681 20.9025 + vertex 200 8.60396 18.9025 + vertex 200 9.44875 17.0051 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 7.38314 20.5828 + vertex 200 10.3557 23.2593 + vertex 200 8.19079 25.2087 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 10.3557 23.2593 + vertex 200 7.38314 20.5828 + vertex 200 8.60396 18.9025 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 8.19079 25.2087 + vertex 200 5.83965 21.9726 + vertex 200 7.38314 20.5828 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 5.66787 26.6653 + vertex 200 5.83965 21.9726 + vertex 200 8.19079 25.2087 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 5.66787 26.6653 + vertex 200 4.04093 23.0111 + vertex 200 5.83965 21.9726 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 2.89725 27.5655 + vertex 200 4.04093 23.0111 + vertex 200 5.66787 26.6653 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 2.89725 27.5655 + vertex 200 2.0656 23.6529 + vertex 200 4.04093 23.0111 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 0 27.87 + vertex 200 2.0656 23.6529 + vertex 200 2.89725 27.5655 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 0 27.87 + vertex 200 0 23.87 + vertex 200 2.0656 23.6529 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 0 27.87 + vertex 200 -2.0656 23.6529 + vertex 200 0 23.87 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -2.89725 27.5655 + vertex 200 -2.0656 23.6529 + vertex 200 0 27.87 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -2.89725 27.5655 + vertex 200 -4.04093 23.0111 + vertex 200 -2.0656 23.6529 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -5.66787 26.6653 + vertex 200 -4.04093 23.0111 + vertex 200 -2.89725 27.5655 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -5.66787 26.6653 + vertex 200 -5.83965 21.9726 + vertex 200 -4.04093 23.0111 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -8.19079 25.2087 + vertex 200 -5.83965 21.9726 + vertex 200 -5.66787 26.6653 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -5.83965 21.9726 + vertex 200 -8.19079 25.2087 + vertex 200 -7.38314 20.5828 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -10.3557 23.2593 + vertex 200 -7.38314 20.5828 + vertex 200 -8.19079 25.2087 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -7.38314 20.5828 + vertex 200 -10.3557 23.2593 + vertex 200 -8.60396 18.9025 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -12.0681 20.9025 + vertex 200 -8.60396 18.9025 + vertex 200 -10.3557 23.2593 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -13.253 18.2412 + vertex 200 -9.44875 17.0051 + vertex 200 -12.0681 20.9025 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -8.60396 18.9025 + vertex 200 -12.0681 20.9025 + vertex 200 -9.44875 17.0051 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 13.253 9.62885 + vertex 200 9.44875 10.8649 + vertex 200 12.0681 6.9675 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 8.60396 8.9675 + vertex 200 12.0681 6.9675 + vertex 200 9.44875 10.8649 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 12.0681 6.9675 + vertex 200 8.60396 8.9675 + vertex 200 10.3557 4.61067 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 7.38314 7.28719 + vertex 200 10.3557 4.61067 + vertex 200 8.60396 8.9675 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 10.3557 4.61067 + vertex 200 7.38314 7.28719 + vertex 200 8.19079 2.66135 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 5.83965 5.89742 + vertex 200 8.19079 2.66135 + vertex 200 7.38314 7.28719 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 5.83965 5.89742 + vertex 200 5.66787 1.20474 + vertex 200 8.19079 2.66135 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 4.04093 4.85893 + vertex 200 5.66787 1.20474 + vertex 200 5.83965 5.89742 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 4.04093 4.85893 + vertex 200 2.89725 0.304514 + vertex 200 5.66787 1.20474 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 2.0656 4.2171 + vertex 200 2.89725 0.304514 + vertex 200 4.04093 4.85893 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 0 4 + vertex 200 2.89725 0.304514 + vertex 200 2.0656 4.2171 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 0 4 + vertex 200 0 5.34058e-07 + vertex 200 2.89725 0.304514 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -2.0656 4.2171 + vertex 200 0 5.34058e-07 + vertex 200 0 4 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -2.0656 4.2171 + vertex 200 -2.89725 0.304514 + vertex 200 0 5.34058e-07 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -4.04093 4.85893 + vertex 200 -2.89725 0.304514 + vertex 200 -2.0656 4.2171 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -4.04093 4.85893 + vertex 200 -5.66787 1.20474 + vertex 200 -2.89725 0.304514 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -5.83965 5.89742 + vertex 200 -5.66787 1.20474 + vertex 200 -4.04093 4.85893 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -8.19079 2.66135 + vertex 200 -5.83965 5.89742 + vertex 200 -7.38314 7.28719 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -5.83965 5.89742 + vertex 200 -8.19079 2.66135 + vertex 200 -5.66787 1.20474 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -10.3557 4.61067 + vertex 200 -7.38314 7.28719 + vertex 200 -8.60396 8.9675 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -12.0681 6.9675 + vertex 200 -8.60396 8.9675 + vertex 200 -9.44875 10.8649 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -13.253 9.62885 + vertex 200 -9.44875 10.8649 + vertex 200 -9.88057 12.8965 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -7.38314 7.28719 + vertex 200 -10.3557 4.61067 + vertex 200 -8.19079 2.66135 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -9.44875 17.0051 + vertex 200 -13.253 18.2412 + vertex 200 -9.88057 14.9735 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 -13.8587 15.3916 + vertex 200 -9.88057 14.9735 + vertex 200 -13.253 18.2412 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -8.60396 8.9675 + vertex 200 -12.0681 6.9675 + vertex 200 -10.3557 4.61067 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -9.88057 14.9735 + vertex 200 -13.8587 15.3916 + vertex 200 -9.88057 12.8965 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -9.44875 10.8649 + vertex 200 -13.253 9.62885 + vertex 200 -12.0681 6.9675 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -13.8587 12.4784 + vertex 200 -9.88057 12.8965 + vertex 200 -13.8587 15.3916 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 -9.88057 12.8965 + vertex 200 -13.8587 12.4784 + vertex 200 -13.253 9.62885 + endloop + endfacet + facet normal 0 0.978147 -0.207915 + outer loop + vertex 200 13.253 9.62885 + vertex 0 13.8587 12.4784 + vertex 200 13.8587 12.4784 + endloop + endfacet + facet normal 0 0.978147 -0.207915 + outer loop + vertex 0 13.8587 12.4784 + vertex 200 13.253 9.62885 + vertex 0 13.253 9.62885 + endloop + endfacet + facet normal 0 0.809007 -0.587799 + outer loop + vertex 200 10.3557 4.61067 + vertex 0 12.0681 6.9675 + vertex 200 12.0681 6.9675 + endloop + endfacet + facet normal 0 0.809007 -0.587799 + outer loop + vertex 0 12.0681 6.9675 + vertex 200 10.3557 4.61067 + vertex 0 10.3557 4.61067 + endloop + endfacet + facet normal 0 0.978148 0.207911 + outer loop + vertex 200 13.8587 15.3916 + vertex 0 13.253 18.2412 + vertex 200 13.253 18.2412 + endloop + endfacet + facet normal 0 0.978148 0.207911 + outer loop + vertex 0 13.253 18.2412 + vertex 200 13.8587 15.3916 + vertex 0 13.8587 15.3916 + endloop + endfacet + facet normal 0 -0.309008 0.951059 + outer loop + vertex 0 -2.89725 27.5655 + vertex 200 -5.66787 26.6653 + vertex 200 -2.89725 27.5655 + endloop + endfacet + facet normal 0 -0.309008 0.951059 + outer loop + vertex 200 -5.66787 26.6653 + vertex 0 -2.89725 27.5655 + vertex 0 -5.66787 26.6653 + endloop + endfacet + facet normal 0 -0.104524 0.994522 + outer loop + vertex 0 0 27.87 + vertex 200 -2.89725 27.5655 + vertex 200 0 27.87 + endloop + endfacet + facet normal 0 -0.104524 0.994522 + outer loop + vertex 200 -2.89725 27.5655 + vertex 0 0 27.87 + vertex 0 -2.89725 27.5655 + endloop + endfacet + facet normal 0 -0.978147 -0.207915 + outer loop + vertex 0 -13.253 9.62885 + vertex 200 -13.8587 12.4784 + vertex 0 -13.8587 12.4784 + endloop + endfacet + facet normal 0 -0.978147 -0.207915 + outer loop + vertex 200 -13.8587 12.4784 + vertex 0 -13.253 9.62885 + vertex 200 -13.253 9.62885 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 0 -13.8587 12.4784 + vertex 200 -13.8587 15.3916 + vertex 0 -13.8587 15.3916 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 200 -13.8587 15.3916 + vertex 0 -13.8587 12.4784 + vertex 200 -13.8587 12.4784 + endloop + endfacet + facet normal 0 -0.669151 0.743127 + outer loop + vertex 0 -8.19079 25.2087 + vertex 200 -10.3557 23.2593 + vertex 200 -8.19079 25.2087 + endloop + endfacet + facet normal 0 -0.669151 0.743127 + outer loop + vertex 200 -10.3557 23.2593 + vertex 0 -8.19079 25.2087 + vertex 0 -10.3557 23.2593 + endloop + endfacet + facet normal 0 -0.809003 0.587804 + outer loop + vertex 0 -12.0681 20.9025 + vertex 200 -10.3557 23.2593 + vertex 0 -10.3557 23.2593 + endloop + endfacet + facet normal 0 -0.809003 0.587804 + outer loop + vertex 200 -10.3557 23.2593 + vertex 0 -12.0681 20.9025 + vertex 200 -12.0681 20.9025 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 9.88057 12.8965 + vertex 0 13.8587 12.4784 + vertex 0 13.253 9.62885 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 13.8587 12.4784 + vertex 0 9.88057 12.8965 + vertex 0 13.8587 15.3916 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 9.44875 10.8649 + vertex 0 13.253 9.62885 + vertex 0 12.0681 6.9675 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 9.88057 14.9735 + vertex 0 13.8587 15.3916 + vertex 0 9.88057 12.8965 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 8.60396 8.9675 + vertex 0 12.0681 6.9675 + vertex 0 10.3557 4.61067 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 13.8587 15.3916 + vertex 0 9.88057 14.9735 + vertex 0 13.253 18.2412 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 9.44875 17.0051 + vertex 0 13.253 18.2412 + vertex 0 9.88057 14.9735 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 13.253 9.62885 + vertex 0 9.44875 10.8649 + vertex 0 9.88057 12.8965 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 12.0681 6.9675 + vertex 0 8.60396 8.9675 + vertex 0 9.44875 10.8649 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 7.38314 7.28719 + vertex 0 10.3557 4.61067 + vertex 0 8.19079 2.66135 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 10.3557 4.61067 + vertex 0 7.38314 7.28719 + vertex 0 8.60396 8.9675 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 8.19079 2.66135 + vertex 0 5.83965 5.89742 + vertex 0 7.38314 7.28719 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 5.66787 1.20474 + vertex 0 5.83965 5.89742 + vertex 0 8.19079 2.66135 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 5.66787 1.20474 + vertex 0 4.04093 4.85893 + vertex 0 5.83965 5.89742 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 2.89725 0.304514 + vertex 0 4.04093 4.85893 + vertex 0 5.66787 1.20474 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 2.89725 0.304514 + vertex 0 2.0656 4.2171 + vertex 0 4.04093 4.85893 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 5.34058e-07 + vertex 0 2.0656 4.2171 + vertex 0 2.89725 0.304514 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 5.34058e-07 + vertex 0 0 4 + vertex 0 2.0656 4.2171 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 5.34058e-07 + vertex 0 -2.0656 4.2171 + vertex 0 0 4 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -2.89725 0.304514 + vertex 0 -2.0656 4.2171 + vertex 0 0 5.34058e-07 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -2.89725 0.304514 + vertex 0 -4.04093 4.85893 + vertex 0 -2.0656 4.2171 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -5.66787 1.20474 + vertex 0 -4.04093 4.85893 + vertex 0 -2.89725 0.304514 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -5.66787 1.20474 + vertex 0 -5.83965 5.89742 + vertex 0 -4.04093 4.85893 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -8.19079 2.66135 + vertex 0 -5.83965 5.89742 + vertex 0 -5.66787 1.20474 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 -5.83965 5.89742 + vertex 0 -8.19079 2.66135 + vertex 0 -7.38314 7.28719 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -10.3557 4.61067 + vertex 0 -7.38314 7.28719 + vertex 0 -8.19079 2.66135 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 -7.38314 7.28719 + vertex 0 -10.3557 4.61067 + vertex 0 -8.60396 8.9675 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -12.0681 6.9675 + vertex 0 -8.60396 8.9675 + vertex 0 -10.3557 4.61067 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -13.253 9.62885 + vertex 0 -9.44875 10.8649 + vertex 0 -12.0681 6.9675 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 -8.60396 8.9675 + vertex 0 -12.0681 6.9675 + vertex 0 -9.44875 10.8649 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 13.253 18.2412 + vertex 0 9.44875 17.0051 + vertex 0 12.0681 20.9025 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 8.60396 18.9025 + vertex 0 12.0681 20.9025 + vertex 0 9.44875 17.0051 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 12.0681 20.9025 + vertex 0 8.60396 18.9025 + vertex 0 10.3557 23.2593 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 7.38314 20.5828 + vertex 0 10.3557 23.2593 + vertex 0 8.60396 18.9025 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 10.3557 23.2593 + vertex 0 7.38314 20.5828 + vertex 0 8.19079 25.2087 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 5.83965 21.9726 + vertex 0 8.19079 25.2087 + vertex 0 7.38314 20.5828 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 5.83965 21.9726 + vertex 0 5.66787 26.6653 + vertex 0 8.19079 25.2087 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 4.04093 23.0111 + vertex 0 5.66787 26.6653 + vertex 0 5.83965 21.9726 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 4.04093 23.0111 + vertex 0 2.89725 27.5655 + vertex 0 5.66787 26.6653 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 2.0656 23.6529 + vertex 0 2.89725 27.5655 + vertex 0 4.04093 23.0111 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 23.87 + vertex 0 2.89725 27.5655 + vertex 0 2.0656 23.6529 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 23.87 + vertex 0 0 27.87 + vertex 0 2.89725 27.5655 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -2.0656 23.6529 + vertex 0 0 27.87 + vertex 0 0 23.87 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -2.0656 23.6529 + vertex 0 -2.89725 27.5655 + vertex 0 0 27.87 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -4.04093 23.0111 + vertex 0 -2.89725 27.5655 + vertex 0 -2.0656 23.6529 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -4.04093 23.0111 + vertex 0 -5.66787 26.6653 + vertex 0 -2.89725 27.5655 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -5.83965 21.9726 + vertex 0 -5.66787 26.6653 + vertex 0 -4.04093 23.0111 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -8.19079 25.2087 + vertex 0 -5.83965 21.9726 + vertex 0 -7.38314 20.5828 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -5.83965 21.9726 + vertex 0 -8.19079 25.2087 + vertex 0 -5.66787 26.6653 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -10.3557 23.2593 + vertex 0 -7.38314 20.5828 + vertex 0 -8.60396 18.9025 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -12.0681 20.9025 + vertex 0 -8.60396 18.9025 + vertex 0 -9.44875 17.0051 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -13.253 18.2412 + vertex 0 -9.44875 17.0051 + vertex 0 -9.88057 14.9735 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -7.38314 20.5828 + vertex 0 -10.3557 23.2593 + vertex 0 -8.19079 25.2087 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 -9.44875 10.8649 + vertex 0 -13.253 9.62885 + vertex 0 -9.88057 12.8965 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -13.8587 12.4784 + vertex 0 -9.88057 12.8965 + vertex 0 -13.253 9.62885 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -8.60396 18.9025 + vertex 0 -12.0681 20.9025 + vertex 0 -10.3557 23.2593 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 -9.88057 12.8965 + vertex 0 -13.8587 12.4784 + vertex 0 -9.88057 14.9735 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -9.44875 17.0051 + vertex 0 -13.253 18.2412 + vertex 0 -12.0681 20.9025 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -13.8587 15.3916 + vertex 0 -9.88057 14.9735 + vertex 0 -13.8587 12.4784 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 -9.88057 14.9735 + vertex 0 -13.8587 15.3916 + vertex 0 -13.253 18.2412 + endloop + endfacet + facet normal 0 0.66914 -0.743136 + outer loop + vertex 0 -7.38314 20.5828 + vertex 200 -5.83965 21.9726 + vertex 200 -7.38314 20.5828 + endloop + endfacet + facet normal 0 0.66914 -0.743136 + outer loop + vertex 200 -5.83965 21.9726 + vertex 0 -7.38314 20.5828 + vertex 0 -5.83965 21.9726 + endloop + endfacet + facet normal 0 -0.30902 0.951056 + outer loop + vertex 0 4.04093 4.85893 + vertex 200 2.0656 4.2171 + vertex 200 4.04093 4.85893 + endloop + endfacet + facet normal 0 -0.30902 0.951056 + outer loop + vertex 200 2.0656 4.2171 + vertex 0 4.04093 4.85893 + vertex 0 2.0656 4.2171 + endloop + endfacet + facet normal 0 -0.104527 0.994522 + outer loop + vertex 0 2.0656 4.2171 + vertex 200 0 4 + vertex 200 2.0656 4.2171 + endloop + endfacet + facet normal 0 -0.104527 0.994522 + outer loop + vertex 200 0 4 + vertex 0 2.0656 4.2171 + vertex 0 0 4 + endloop + endfacet + facet normal 0 -0.499999 0.866026 + outer loop + vertex 0 5.83965 5.89742 + vertex 200 4.04093 4.85893 + vertex 200 5.83965 5.89742 + endloop + endfacet + facet normal 0 -0.499999 0.866026 + outer loop + vertex 200 4.04093 4.85893 + vertex 0 5.83965 5.89742 + vertex 0 4.04093 4.85893 + endloop + endfacet + facet normal -0 0.30902 0.951056 + outer loop + vertex 0 -2.0656 4.2171 + vertex 200 -4.04093 4.85893 + vertex 200 -2.0656 4.2171 + endloop + endfacet + facet normal 0 0.30902 0.951056 + outer loop + vertex 200 -4.04093 4.85893 + vertex 0 -2.0656 4.2171 + vertex 0 -4.04093 4.85893 + endloop + endfacet + facet normal 0 0.809016 0.587786 + outer loop + vertex 200 -7.38314 7.28719 + vertex 0 -8.60396 8.9675 + vertex 200 -8.60396 8.9675 + endloop + endfacet + facet normal 0 0.809016 0.587786 + outer loop + vertex 0 -8.60396 8.9675 + vertex 200 -7.38314 7.28719 + vertex 0 -7.38314 7.28719 + endloop + endfacet + facet normal -0 0.669132 0.743144 + outer loop + vertex 0 -5.83965 5.89742 + vertex 200 -7.38314 7.28719 + vertex 200 -5.83965 5.89742 + endloop + endfacet + facet normal 0 0.669132 0.743144 + outer loop + vertex 200 -7.38314 7.28719 + vertex 0 -5.83965 5.89742 + vertex 0 -7.38314 7.28719 + endloop + endfacet + facet normal -0 0.104527 0.994522 + outer loop + vertex 0 0 4 + vertex 200 -2.0656 4.2171 + vertex 200 0 4 + endloop + endfacet + facet normal 0 0.104527 0.994522 + outer loop + vertex 200 -2.0656 4.2171 + vertex 0 0 4 + vertex 0 -2.0656 4.2171 + endloop + endfacet + facet normal 0 0.913543 -0.406742 + outer loop + vertex 200 -9.44875 17.0051 + vertex 0 -8.60396 18.9025 + vertex 200 -8.60396 18.9025 + endloop + endfacet + facet normal 0 0.913543 -0.406742 + outer loop + vertex 0 -8.60396 18.9025 + vertex 200 -9.44875 17.0051 + vertex 0 -9.44875 17.0051 + endloop + endfacet + facet normal 0 -0.913543 0.406742 + outer loop + vertex 0 8.60396 8.9675 + vertex 200 9.44875 10.8649 + vertex 0 9.44875 10.8649 + endloop + endfacet + facet normal 0 -0.913543 0.406742 + outer loop + vertex 200 9.44875 10.8649 + vertex 0 8.60396 8.9675 + vertex 200 8.60396 8.9675 + endloop + endfacet + facet normal 0 -0.669132 0.743144 + outer loop + vertex 0 7.38314 7.28719 + vertex 200 5.83965 5.89742 + vertex 200 7.38314 7.28719 + endloop + endfacet + facet normal 0 -0.669132 0.743144 + outer loop + vertex 200 5.83965 5.89742 + vertex 0 7.38314 7.28719 + vertex 0 5.83965 5.89742 + endloop + endfacet + facet normal 0 0.809015 -0.587789 + outer loop + vertex 200 -8.60396 18.9025 + vertex 0 -7.38314 20.5828 + vertex 200 -7.38314 20.5828 + endloop + endfacet + facet normal 0 0.809015 -0.587789 + outer loop + vertex 0 -7.38314 20.5828 + vertex 200 -8.60396 18.9025 + vertex 0 -8.60396 18.9025 + endloop + endfacet + facet normal 0 -0.66914 -0.743136 + outer loop + vertex 0 5.83965 21.9726 + vertex 200 7.38314 20.5828 + vertex 200 5.83965 21.9726 + endloop + endfacet + facet normal -0 -0.66914 -0.743136 + outer loop + vertex 200 7.38314 20.5828 + vertex 0 5.83965 21.9726 + vertex 0 7.38314 20.5828 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 0 9.88057 12.8965 + vertex 200 9.88057 14.9735 + vertex 0 9.88057 14.9735 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 200 9.88057 14.9735 + vertex 0 9.88057 12.8965 + vertex 200 9.88057 12.8965 + endloop + endfacet + facet normal 0 0.913543 0.406742 + outer loop + vertex 200 -8.60396 8.9675 + vertex 0 -9.44875 10.8649 + vertex 200 -9.44875 10.8649 + endloop + endfacet + facet normal 0 0.913543 0.406742 + outer loop + vertex 0 -9.44875 10.8649 + vertex 200 -8.60396 8.9675 + vertex 0 -8.60396 8.9675 + endloop + endfacet + facet normal 0 0.978149 0.207907 + outer loop + vertex 200 -9.44875 10.8649 + vertex 0 -9.88057 12.8965 + vertex 200 -9.88057 12.8965 + endloop + endfacet + facet normal 0 0.978149 0.207907 + outer loop + vertex 0 -9.88057 12.8965 + vertex 200 -9.44875 10.8649 + vertex 0 -9.44875 10.8649 + endloop + endfacet + facet normal 0 -0.309007 -0.95106 + outer loop + vertex 0 2.0656 23.6529 + vertex 200 4.04093 23.0111 + vertex 200 2.0656 23.6529 + endloop + endfacet + facet normal -0 -0.309007 -0.95106 + outer loop + vertex 200 4.04093 23.0111 + vertex 0 2.0656 23.6529 + vertex 0 4.04093 23.0111 + endloop + endfacet + facet normal 0 0.309007 -0.95106 + outer loop + vertex 0 -4.04093 23.0111 + vertex 200 -2.0656 23.6529 + vertex 200 -4.04093 23.0111 + endloop + endfacet + facet normal 0 0.309007 -0.95106 + outer loop + vertex 200 -2.0656 23.6529 + vertex 0 -4.04093 23.0111 + vertex 0 -2.0656 23.6529 + endloop + endfacet + facet normal 0 -0.913543 -0.406742 + outer loop + vertex 0 9.44875 17.0051 + vertex 200 8.60396 18.9025 + vertex 0 8.60396 18.9025 + endloop + endfacet + facet normal 0 -0.913543 -0.406742 + outer loop + vertex 200 8.60396 18.9025 + vertex 0 9.44875 17.0051 + vertex 200 9.44875 17.0051 + endloop + endfacet + facet normal 0 0.978149 -0.207907 + outer loop + vertex 200 -9.88057 14.9735 + vertex 0 -9.44875 17.0051 + vertex 200 -9.44875 17.0051 + endloop + endfacet + facet normal 0 0.978149 -0.207907 + outer loop + vertex 0 -9.44875 17.0051 + vertex 200 -9.88057 14.9735 + vertex 0 -9.88057 14.9735 + endloop + endfacet + facet normal 0 -0.978149 0.207907 + outer loop + vertex 0 9.44875 10.8649 + vertex 200 9.88057 12.8965 + vertex 0 9.88057 12.8965 + endloop + endfacet + facet normal 0 -0.978149 0.207907 + outer loop + vertex 200 9.88057 12.8965 + vertex 0 9.44875 10.8649 + vertex 200 9.44875 10.8649 + endloop + endfacet + facet normal 0 0.104527 -0.994522 + outer loop + vertex 0 -2.0656 23.6529 + vertex 200 0 23.87 + vertex 200 -2.0656 23.6529 + endloop + endfacet + facet normal 0 0.104527 -0.994522 + outer loop + vertex 200 0 23.87 + vertex 0 -2.0656 23.6529 + vertex 0 0 23.87 + endloop + endfacet + facet normal 0 -0.104527 -0.994522 + outer loop + vertex 0 0 23.87 + vertex 200 2.0656 23.6529 + vertex 200 0 23.87 + endloop + endfacet + facet normal -0 -0.104527 -0.994522 + outer loop + vertex 200 2.0656 23.6529 + vertex 0 0 23.87 + vertex 0 2.0656 23.6529 + endloop + endfacet + facet normal 0 0.500003 -0.866024 + outer loop + vertex 0 -5.83965 21.9726 + vertex 200 -4.04093 23.0111 + vertex 200 -5.83965 21.9726 + endloop + endfacet + facet normal 0 0.500003 -0.866024 + outer loop + vertex 200 -4.04093 23.0111 + vertex 0 -5.83965 21.9726 + vertex 0 -4.04093 23.0111 + endloop + endfacet + facet normal 0 -0.500003 -0.866024 + outer loop + vertex 0 4.04093 23.0111 + vertex 200 5.83965 21.9726 + vertex 200 4.04093 23.0111 + endloop + endfacet + facet normal -0 -0.500003 -0.866024 + outer loop + vertex 200 5.83965 21.9726 + vertex 0 4.04093 23.0111 + vertex 0 5.83965 21.9726 + endloop + endfacet + facet normal -0 0.499999 0.866026 + outer loop + vertex 0 -4.04093 4.85893 + vertex 200 -5.83965 5.89742 + vertex 200 -4.04093 4.85893 + endloop + endfacet + facet normal 0 0.499999 0.866026 + outer loop + vertex 200 -5.83965 5.89742 + vertex 0 -4.04093 4.85893 + vertex 0 -5.83965 5.89742 + endloop + endfacet + facet normal 0 -0.809016 0.587786 + outer loop + vertex 0 7.38314 7.28719 + vertex 200 8.60396 8.9675 + vertex 0 8.60396 8.9675 + endloop + endfacet + facet normal 0 -0.809016 0.587786 + outer loop + vertex 200 8.60396 8.9675 + vertex 0 7.38314 7.28719 + vertex 200 7.38314 7.28719 + endloop + endfacet + facet normal 0 -0.809015 -0.587789 + outer loop + vertex 0 8.60396 18.9025 + vertex 200 7.38314 20.5828 + vertex 0 7.38314 20.5828 + endloop + endfacet + facet normal 0 -0.809015 -0.587789 + outer loop + vertex 200 7.38314 20.5828 + vertex 0 8.60396 18.9025 + vertex 200 8.60396 18.9025 + endloop + endfacet + facet normal 0 -0.978149 -0.207907 + outer loop + vertex 0 9.88057 14.9735 + vertex 200 9.44875 17.0051 + vertex 0 9.44875 17.0051 + endloop + endfacet + facet normal 0 -0.978149 -0.207907 + outer loop + vertex 200 9.44875 17.0051 + vertex 0 9.88057 14.9735 + vertex 200 9.88057 14.9735 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 200 -9.88057 12.8965 + vertex 0 -9.88057 14.9735 + vertex 200 -9.88057 14.9735 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 0 -9.88057 14.9735 + vertex 200 -9.88057 12.8965 + vertex 0 -9.88057 12.8965 + endloop + endfacet +endsolid OpenSCAD_Model diff --git a/files/benchmark-square.stl b/files/benchmark-square.stl new file mode 100644 index 000000000..379e3838e --- /dev/null +++ b/files/benchmark-square.stl @@ -0,0 +1,86 @@ +solid OpenSCAD_Model + facet normal -0 0 1 + outer loop + vertex 0 17.32 17.32 + vertex 200 0 17.32 + vertex 200 17.32 17.32 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 200 0 17.32 + vertex 0 17.32 17.32 + vertex 0 0 17.32 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 0 0 0 + vertex 200 17.32 0 + vertex 200 0 0 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 200 17.32 0 + vertex 0 0 0 + vertex 0 17.32 0 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 0 0 0 + vertex 200 0 17.32 + vertex 0 0 17.32 + endloop + endfacet + facet normal 0 -1 -0 + outer loop + vertex 200 0 17.32 + vertex 0 0 0 + vertex 200 0 0 + endloop + endfacet + facet normal 1 -0 0 + outer loop + vertex 200 0 17.32 + vertex 200 17.32 0 + vertex 200 17.32 17.32 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 200 17.32 0 + vertex 200 0 17.32 + vertex 200 0 0 + endloop + endfacet + facet normal 0 1 -0 + outer loop + vertex 200 17.32 0 + vertex 0 17.32 17.32 + vertex 200 17.32 17.32 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 0 17.32 17.32 + vertex 200 17.32 0 + vertex 0 17.32 0 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 0 0 0 + vertex 0 17.32 17.32 + vertex 0 17.32 0 + endloop + endfacet + facet normal -1 -0 0 + outer loop + vertex 0 17.32 17.32 + vertex 0 0 0 + vertex 0 0 17.32 + endloop + endfacet +endsolid OpenSCAD_Model From eb9229f7988fc2b7ef6667cfe44335205c04032c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 16:11:41 +0330 Subject: [PATCH 564/775] Increase restraint location threshold --- examples/finite_elements/benchmark-squre.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/finite_elements/benchmark-squre.go b/examples/finite_elements/benchmark-squre.go index 82e719cfb..0adbc30c2 100644 --- a/examples/finite_elements/benchmark-squre.go +++ b/examples/finite_elements/benchmark-squre.go @@ -9,18 +9,18 @@ func restraintSquare(x, y, z float64) (bool, bool, bool) { node := v3.Vec{X: x, Y: y, Z: z} // All three degrees of freedom are fixed. - if node.Equals(v3.Vec{X: 0, Y: 0, Z: 0}, 0.01) { + if node.Equals(v3.Vec{X: 0, Y: 0, Z: 0}, 2) { return true, true, true } - if node.Equals(v3.Vec{X: 0, Y: 17.32, Z: 0}, 0.01) { + if node.Equals(v3.Vec{X: 0, Y: 17.32, Z: 0}, 2) { return true, true, true } // Some degrees of freedom are fixed. - if node.Equals(v3.Vec{X: 200, Y: 0, Z: 0}, 0.01) { + if node.Equals(v3.Vec{X: 200, Y: 0, Z: 0}, 2) { return false, true, true } - if node.Equals(v3.Vec{X: 200, Y: 17.32, Z: 0}, 0.01) { + if node.Equals(v3.Vec{X: 200, Y: 17.32, Z: 0}, 2) { return false, true, true } return false, false, false From 3d3150763c0c35c23d2209a888e557812961437e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 16:14:19 +0330 Subject: [PATCH 565/775] Fix file name: typo --- .../finite_elements/{benchmark-squre.go => benchmark-square.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/finite_elements/{benchmark-squre.go => benchmark-square.go} (100%) diff --git a/examples/finite_elements/benchmark-squre.go b/examples/finite_elements/benchmark-square.go similarity index 100% rename from examples/finite_elements/benchmark-squre.go rename to examples/finite_elements/benchmark-square.go From 9db58325ef8ff911c6c5fcaafb8a1034925de66f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 12 Jul 2023 16:15:23 +0330 Subject: [PATCH 566/775] Fix file name: typo --- .../finite_elements/{benchmark-circule.go => benchmark-circle.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/finite_elements/{benchmark-circule.go => benchmark-circle.go} (100%) diff --git a/examples/finite_elements/benchmark-circule.go b/examples/finite_elements/benchmark-circle.go similarity index 100% rename from examples/finite_elements/benchmark-circule.go rename to examples/finite_elements/benchmark-circle.go From 5b022e556802e41b1dc905fb76ab699eb446105b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 13 Jul 2023 09:33:32 +0330 Subject: [PATCH 567/775] Remove logic that avoids repeated boundary nodes: It was buggy. --- render/finiteelements/mesh/inp.go | 103 +++++++++++++----------------- 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 9a56ec500..92c99fdc6 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -41,8 +41,6 @@ type Inp struct { eleID uint32 // Just a counter to keep track of written nodes nextNode uint32 - // Just a counter to keep track of written boundaries - nextNodeBou uint32 // Inside the function, according to the x, y, z, the caller decides on restraint. Restraint func(x, y, z float64) (bool, bool, bool) // Inside the function, according to the x, y, z, the caller decides on load. @@ -353,11 +351,7 @@ func (inp *Inp) writeBoundary() error { return err } - var process func(int, int, int, []*buffer.Element) - - inp.nextNodeBou = 1 // ID starts from one not zero. - - process = func(x, y, z int, els []*buffer.Element) { + process := func(x, y, z int, els []*buffer.Element) { for _, el := range els { vertices := make([]v3.Vec, len(el.Nodes)) ids := make([]uint32, len(el.Nodes)) @@ -376,57 +370,52 @@ func (inp *Inp) writeBoundary() error { // ID starts from one not zero. - // Only write node if it's not already written to file. - if ids[n]+1 == inp.nextNodeBou { - - // To be written: - // 1) Node number/ID. - // 2) First degree of freedom constrained. - // 3) Last degree of freedom constrained. This field may be left blank if only - // one degree of freedom is constrained. - - if isFixedX && isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if isFixedX && isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1,2\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if !isFixedX && isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,2,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if isFixedX && !isFixedY && isFixedZ { - // TODO: Can we write this case by just one line, not two lines? - _, err = f.WriteString(fmt.Sprintf("%d,1\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - _, err = f.WriteString(fmt.Sprintf("%d,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if isFixedX && !isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if !isFixedX && isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,2\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if !isFixedX && !isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } + // To be written: + // 1) Node number/ID. + // 2) First degree of freedom constrained. + // 3) Last degree of freedom constrained. This field may be left blank if only + // one degree of freedom is constrained. + + if isFixedX && isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1,2\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,2,3\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && !isFixedY && isFixedZ { + // TODO: Can we write this case by just one line, not two lines? + _, err = f.WriteString(fmt.Sprintf("%d,1\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,3\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && !isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,2\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && !isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,3\n", ids[n]+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) } - inp.nextNodeBou++ } } } From eae05b58f8f135d632d45ea2d460aee21fbdfc8e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 15 Jul 2023 16:21:33 +0330 Subject: [PATCH 568/775] Remove outdated files --- examples/finite_elements/benchmark-I.go | 1 - examples/finite_elements/benchmark-circle.go | 1 - examples/finite_elements/benchmark-pipe.go | 1 - examples/finite_elements/benchmark-square.go | 31 -------------------- 4 files changed, 34 deletions(-) delete mode 100644 examples/finite_elements/benchmark-I.go delete mode 100644 examples/finite_elements/benchmark-circle.go delete mode 100644 examples/finite_elements/benchmark-pipe.go delete mode 100644 examples/finite_elements/benchmark-square.go diff --git a/examples/finite_elements/benchmark-I.go b/examples/finite_elements/benchmark-I.go deleted file mode 100644 index 06ab7d0f9..000000000 --- a/examples/finite_elements/benchmark-I.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/examples/finite_elements/benchmark-circle.go b/examples/finite_elements/benchmark-circle.go deleted file mode 100644 index 06ab7d0f9..000000000 --- a/examples/finite_elements/benchmark-circle.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/examples/finite_elements/benchmark-pipe.go b/examples/finite_elements/benchmark-pipe.go deleted file mode 100644 index 06ab7d0f9..000000000 --- a/examples/finite_elements/benchmark-pipe.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/examples/finite_elements/benchmark-square.go b/examples/finite_elements/benchmark-square.go deleted file mode 100644 index 0adbc30c2..000000000 --- a/examples/finite_elements/benchmark-square.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import v3 "github.com/deadsy/sdfx/vec/v3" - -// The 3D beam is simply supported i.e. one end is pinned and the other end is roller. -// Benchmark reference: -// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections -func restraintSquare(x, y, z float64) (bool, bool, bool) { - node := v3.Vec{X: x, Y: y, Z: z} - - // All three degrees of freedom are fixed. - if node.Equals(v3.Vec{X: 0, Y: 0, Z: 0}, 2) { - return true, true, true - } - if node.Equals(v3.Vec{X: 0, Y: 17.32, Z: 0}, 2) { - return true, true, true - } - - // Some degrees of freedom are fixed. - if node.Equals(v3.Vec{X: 200, Y: 0, Z: 0}, 2) { - return false, true, true - } - if node.Equals(v3.Vec{X: 200, Y: 17.32, Z: 0}, 2) { - return false, true, true - } - return false, false, false -} - -func loadSquare(x, y, z float64) (float64, float64, float64) { - return 0, 0, 0 -} From 7aadd9cfc980f555df95859344ab3053cd6264a1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 15 Jul 2023 17:05:38 +0330 Subject: [PATCH 569/775] Pass restraints and loads --- examples/finite_elements/main.go | 45 ++++++++++++++++--------------- render/finiteelements/mesh/fem.go | 12 ++++----- render/finiteelements/mesh/inp.go | 16 +++++------ 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 660efe7f1..5598bdcc6 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -49,9 +49,12 @@ func main() { benchmark = Benchmark(bmint) } + restraints := []*mesh.Restraint{} + loads := []*mesh.Load{} + switch benchmark { case Square: - benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraintSquare, loadSquare) + benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraints, loads) case Circle: case Pipe: case I: @@ -65,8 +68,8 @@ func benchmarkRun( stl string, resolution int, layerStart, layerEnd int, - restraint func(x, y, z float64) (bool, bool, bool), - load func(x, y, z float64) (float64, float64, float64), + restraints []*mesh.Restraint, + loads []*mesh.Load, ) { // read the stl file. file, err := os.OpenFile(stl, os.O_RDONLY, 0400) @@ -81,7 +84,7 @@ func benchmarkRun( } // tet4 i.e. 4-node tetrahedron - err = fe(inSdf, resolution, render.Linear, render.Tetrahedral, "tet4.inp", restraint, load) + err = fe(inSdf, resolution, render.Linear, render.Tetrahedral, "tet4.inp", restraints, loads) if err != nil { log.Fatalf("error: %s", err) } @@ -90,14 +93,14 @@ func benchmarkRun( err = feLayers( inSdf, resolution, render.Linear, render.Tetrahedral, fmt.Sprintf("tet4--layers-%v-to-%v.inp", layerStart, layerEnd), - restraint, load, layerStart, layerEnd, + restraints, loads, layerStart, layerEnd, ) if err != nil { log.Fatalf("error: %s", err) } // tet10 i.e. 10-node tetrahedron - err = fe(inSdf, resolution, render.Quadratic, render.Tetrahedral, "tet10.inp", restraint, load) + err = fe(inSdf, resolution, render.Quadratic, render.Tetrahedral, "tet10.inp", restraints, loads) if err != nil { log.Fatalf("error: %s", err) } @@ -106,14 +109,14 @@ func benchmarkRun( err = feLayers( inSdf, resolution, render.Quadratic, render.Tetrahedral, fmt.Sprintf("tet10--layers-%v-to-%v.inp", layerStart, layerEnd), - restraint, load, layerStart, layerEnd, + restraints, loads, layerStart, layerEnd, ) if err != nil { log.Fatalf("error: %s", err) } // hex8 i.e. 8-node hexahedron - err = fe(inSdf, resolution, render.Linear, render.Hexahedral, "hex8.inp", restraint, load) + err = fe(inSdf, resolution, render.Linear, render.Hexahedral, "hex8.inp", restraints, loads) if err != nil { log.Fatalf("error: %s", err) } @@ -121,14 +124,14 @@ func benchmarkRun( // hex8 i.e. 8-node hexahedron err = feLayers(inSdf, resolution, render.Linear, render.Hexahedral, fmt.Sprintf("hex8--layers-%v-to-%v.inp", layerStart, layerEnd), - restraint, load, layerStart, layerEnd, + restraints, loads, layerStart, layerEnd, ) if err != nil { log.Fatalf("error: %s", err) } // hex20 i.e. 20-node hexahedron - err = fe(inSdf, resolution, render.Quadratic, render.Hexahedral, "hex20.inp", restraint, load) + err = fe(inSdf, resolution, render.Quadratic, render.Hexahedral, "hex20.inp", restraints, loads) if err != nil { log.Fatalf("error: %s", err) } @@ -136,14 +139,14 @@ func benchmarkRun( // hex20 i.e. 20-node hexahedron err = feLayers(inSdf, resolution, render.Quadratic, render.Hexahedral, fmt.Sprintf("hex20--layers-%v-to-%v.inp", layerStart, layerEnd), - restraint, load, layerStart, layerEnd, + restraints, loads, layerStart, layerEnd, ) if err != nil { log.Fatalf("error: %s", err) } // hex8 and tet4 - err = fe(inSdf, resolution, render.Linear, render.Both, "hex8tet4.inp", restraint, load) + err = fe(inSdf, resolution, render.Linear, render.Both, "hex8tet4.inp", restraints, loads) if err != nil { log.Fatalf("error: %s", err) } @@ -151,14 +154,14 @@ func benchmarkRun( // hex8 and tet4 err = feLayers(inSdf, resolution, render.Linear, render.Both, fmt.Sprintf("hex8tet4--layers-%v-to-%v.inp", layerStart, layerEnd), - restraint, load, layerStart, layerEnd, + restraints, loads, layerStart, layerEnd, ) if err != nil { log.Fatalf("error: %s", err) } // hex20 and tet10 - err = fe(inSdf, resolution, render.Quadratic, render.Both, "hex20tet10.inp", restraint, load) + err = fe(inSdf, resolution, render.Quadratic, render.Both, "hex20tet10.inp", restraints, loads) if err != nil { log.Fatalf("error: %s", err) } @@ -166,7 +169,7 @@ func benchmarkRun( // hex20 and tet10 err = feLayers(inSdf, resolution, render.Quadratic, render.Both, fmt.Sprintf("hex20tet10--layers-%v-to-%v.inp", layerStart, layerEnd), - restraint, load, layerStart, layerEnd, + restraints, loads, layerStart, layerEnd, ) if err != nil { log.Fatalf("error: %s", err) @@ -175,8 +178,8 @@ func benchmarkRun( // Generate finite elements. func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, - restraint func(x, y, z float64) (bool, bool, bool), - load func(x, y, z float64) (float64, float64, float64), + restraints []*mesh.Restraint, + loads []*mesh.Load, ) error { s = dilationErosion(s) @@ -184,15 +187,15 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write all layers of mesh to file. - return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraint, load, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) + return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) } // Generate finite elements. // Only from a start layer to an end layer along the Z axis. // Applicable to 3D print analysis that is done layer-by-layer. func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, - restraint func(x, y, z float64) (bool, bool, bool), - load func(x, y, z float64) (float64, float64, float64), + restraints []*mesh.Restraint, + loads []*mesh.Load, layerStart, layerEnd int, ) error { s = dilationErosion(s) @@ -201,7 +204,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) // Write just some layers of mesh to file. - return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraint, load, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) + return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) } // By dilating SDF a little bit we may actually get rid of diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index a159abe7d..f16b18dd3 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -82,13 +82,13 @@ func (m *Fem) WriteInp( massDensity float32, youngModulus float32, poissonRatio float32, - restraint func(x, y, z float64) (bool, bool, bool), - load func(x, y, z float64) (float64, float64, float64), + restraints []*Restraint, + loads []*Load, gravityDirection v3.Vec, gravityMagnitude float64, ) error { _, _, layersZ := m.IBuff.Size() - return m.WriteInpLayers(path, 0, layersZ, massDensity, youngModulus, poissonRatio, restraint, load, gravityDirection, gravityMagnitude) + return m.WriteInpLayers(path, 0, layersZ, massDensity, youngModulus, poissonRatio, restraints, loads, gravityDirection, gravityMagnitude) } // WriteInpLayers writes specific layers of mesh to ABAQUS or CalculiX `inp` file. @@ -100,12 +100,12 @@ func (m *Fem) WriteInpLayers( massDensity float32, youngModulus float32, poissonRatio float32, - restraint func(x, y, z float64) (bool, bool, bool), - load func(x, y, z float64) (float64, float64, float64), + restraints []*Restraint, + loads []*Load, gravityDirection v3.Vec, gravityMagnitude float64, ) error { - inp := NewInp(m, path, layerStart, layerEnd, massDensity, youngModulus, poissonRatio, restraint, load, gravityDirection, gravityMagnitude) + inp := NewInp(m, path, layerStart, layerEnd, massDensity, youngModulus, poissonRatio, restraints, loads, gravityDirection, gravityMagnitude) return inp.Write() } diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 92c99fdc6..6bb00fcb9 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -41,10 +41,10 @@ type Inp struct { eleID uint32 // Just a counter to keep track of written nodes nextNode uint32 - // Inside the function, according to the x, y, z, the caller decides on restraint. - Restraint func(x, y, z float64) (bool, bool, bool) - // Inside the function, according to the x, y, z, the caller decides on load. - Load func(x, y, z float64) (float64, float64, float64) + // Single point constraint: one or more degrees of freedom are fixed for a given node. Passed in by the caller. + Restraints []*Restraint + // Point loads are applied to the nodes of the mesh. Passed in by the caller. + Loads []*Load // Assigns gravity loading in this direction to all elements. GravityDirection v3.Vec // Assigns gravity loading with magnitude to all elements. @@ -57,8 +57,8 @@ func NewInp( path string, layerStart, layerEnd int, massDensity float32, youngModulus float32, poissonRatio float32, - restraint func(x, y, z float64) (bool, bool, bool), - load func(x, y, z float64) (float64, float64, float64), + restraints []*Restraint, + loads []*Load, gravityDirection v3.Vec, gravityMagnitude float64, ) *Inp { @@ -77,8 +77,8 @@ func NewInp( MassDensity: massDensity, YoungModulus: youngModulus, PoissonRatio: poissonRatio, - Restraint: restraint, - Load: load, + Restraints: restraints, + Loads: loads, GravityDirection: gravityDirection, GravityMagnitude: gravityMagnitude, } From 1d1917324422bdd7ce33761b8b8f4699c9ed5b19 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 09:55:19 +0330 Subject: [PATCH 570/775] New file for restraint & load --- render/finiteelements/mesh/restraint_load.go | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 render/finiteelements/mesh/restraint_load.go diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go new file mode 100644 index 000000000..aa588d19b --- /dev/null +++ b/render/finiteelements/mesh/restraint_load.go @@ -0,0 +1,44 @@ +package mesh + +import ( + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" +) + +// Single point constraint: one or more degrees of freedom are fixed for a given node. +type Restraint struct { + Location v3.Vec // Exact coordinate. + IsFixedX bool // Is X degree of freedom fixed? + IsFixedY bool // Is Y degree of freedom fixed? + IsFixedZ bool // Is Z degree of freedom fixed? + voxel v3i.Vec // Containing voxel: to be computed by logic. + nodeID int // Eventual node to which the restraint is applied. To be computed. +} + +// Point loads are applied to the nodes of the mesh. +type Load struct { + Location v3.Vec // Exact coordinate. + Magnitude v3.Vec // X, Y, Z magnitude. + voxel v3i.Vec // Containing voxel: to be computed by logic. + nodeID int // Eventual node to which the load is applied. To be computed. +} + +func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { + return &Restraint{ + Location: location, + IsFixedX: isFixedX, + IsFixedY: isFixedY, + IsFixedZ: isFixedZ, + voxel: v3i.Vec{}, + nodeID: 0, + } +} + +func NewLoad(location, magnitude v3.Vec) *Load { + return &Load{ + Location: location, + Magnitude: magnitude, + voxel: v3i.Vec{}, + nodeID: 0, + } +} From 7fe34424b91e712510421a4588723c552a0f3929 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 10:01:06 +0330 Subject: [PATCH 571/775] Initialize restraints --- examples/finite_elements/main.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 5598bdcc6..70b708c7e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -49,15 +49,23 @@ func main() { benchmark = Benchmark(bmint) } - restraints := []*mesh.Restraint{} + restraints := []*mesh.Restraint{ + mesh.NewRestraint(v3.Vec{X: 0, Y: 0, Z: 0}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: 17.32, Z: 0}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 17.32, Z: 0}, false, true, true), + } loads := []*mesh.Load{} switch benchmark { case Square: benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraints, loads) case Circle: + benchmarkRun("../../files/benchmark-circle.stl", 50, 0, 3, restraints, loads) case Pipe: + benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads) case I: + benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads) default: } } From a88046a342c08cb74beb3ca04ecf68e51c37f5df Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 10:02:35 +0330 Subject: [PATCH 572/775] Comment --- examples/finite_elements/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 70b708c7e..8fd505387 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -55,6 +55,7 @@ func main() { mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), mesh.NewRestraint(v3.Vec{X: 200, Y: 17.32, Z: 0}, false, true, true), } + // Gravity load is used for benchmarks. So, there is no point load. loads := []*mesh.Load{} switch benchmark { From 4158a47f54b02ecac2032f61ea0e24e33c526199 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 10:11:50 +0330 Subject: [PATCH 573/775] Function to find node & voxel for restraint --- render/finiteelements/mesh/inp.go | 9 ++++++++- render/finiteelements/mesh/restraint_load.go | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 6bb00fcb9..560002ac3 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -62,7 +62,7 @@ func NewInp( gravityDirection v3.Vec, gravityMagnitude float64, ) *Inp { - return &Inp{ + inp := &Inp{ Mesh: m, Path: path, PathNodes: path + ".nodes", @@ -82,6 +82,13 @@ func NewInp( GravityDirection: gravityDirection, GravityMagnitude: gravityMagnitude, } + + // Figure out node and voxel for each restraint. + for _, r := range inp.Restraints { + r.FindNode() + } + + return inp } // Write starts writing to `inp` file. diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index aa588d19b..75ea12d0b 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -42,3 +42,9 @@ func NewLoad(location, magnitude v3.Vec) *Load { nodeID: 0, } } + +// Identify the node to which restraint is applied. +// Also, the containing voxel is figured out. +func (r *Restraint) FindNode() { + // TODO. +} From 9fdea4400abb88a5760583870520b2403cc9c9ca Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 10:13:09 +0330 Subject: [PATCH 574/775] TODO --- examples/finite_elements/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 8fd505387..ef67b73a0 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -219,6 +219,8 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape // By dilating SDF a little bit we may actually get rid of // bad elements like disconnected or improperly connected elements. // Erode so that SDF returns to its original size, well almost. +// +// TODO: run benchmarks without this to test. func dilationErosion(s sdf.SDF3) sdf.SDF3 { min := s.BoundingBox().Min max := s.BoundingBox().Max From 15bfc453f89ee3c500d2451efe208af668f0b442 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 10:45:48 +0330 Subject: [PATCH 575/775] Get ready to store voxel min & max coordinates --- render/finiteelements/buffer/voxel.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index de8a45a70..2b60abfa6 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -1,5 +1,7 @@ package buffer +import v3 "github.com/deadsy/sdfx/vec/v3" + type Element struct { Nodes []uint32 // Node indices } @@ -35,20 +37,26 @@ func NewElement(nodes []uint32) *Element { return &e } +type Voxel struct { + data []*Element // Each voxel stores multiple elements. + min v3.Vec // Min corner of voxel. + max v3.Vec // Max corner of voxel. +} + // Acts like a three-dimensional nested slice using // a one-dimensional slice under the hood. // To increase performance. type VoxelGrid struct { - data [][]*Element // Each voxel stores multiple elements. - lenX, lenY, lenZ int // Voxels count in 3 directions. + voxels []*Voxel // + lenX, lenY, lenZ int // Voxels count in 3 directions. } func NewVoxelGrid(x, y, z int) *VoxelGrid { return &VoxelGrid{ - data: make([][]*Element, x*y*z), - lenX: x, - lenY: y, - lenZ: z, + voxels: make([]*Voxel, x*y*z), + lenX: x, + lenY: y, + lenZ: z, } } @@ -58,17 +66,17 @@ func (vg *VoxelGrid) Size() (int, int, int) { // To get all the elements inside a voxel. func (vg *VoxelGrid) Get(x, y, z int) []*Element { - return vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] + return vg.voxels[x*vg.lenY*vg.lenZ+y*vg.lenZ+z].data } // To set all the elements inside a voxel at once. func (vg *VoxelGrid) Set(x, y, z int, value []*Element) { - vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] = value + vg.voxels[x*vg.lenY*vg.lenZ+y*vg.lenZ+z].data = value } // To append a single element to the elements inside a voxel. func (vg *VoxelGrid) Append(x, y, z int, value *Element) { - vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z] = append(vg.data[x*vg.lenY*vg.lenZ+y*vg.lenZ+z], value) + vg.voxels[x*vg.lenY*vg.lenZ+y*vg.lenZ+z].data = append(vg.voxels[x*vg.lenY*vg.lenZ+y*vg.lenZ+z].data, value) } // To iterate over all voxels and get elements inside each voxel and do stuff with them. From 5fa5868efdfbac857e0e706119e18b384df7e4ab Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 13:00:46 +0330 Subject: [PATCH 576/775] Identify the min & max corners for each voxel --- render/finiteelements/buffer/indexbuffer.go | 6 ++- render/finiteelements/buffer/voxel.go | 19 +++++++- render/finiteelements/mesh/fem.go | 10 ++-- render/finiteelements/mesh/inp.go | 4 +- render/marchfe.go | 54 +++++++++++++++++---- render/render.go | 7 +-- 6 files changed, 78 insertions(+), 22 deletions(-) diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index b5d36ad55..ecfae4b14 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -1,13 +1,15 @@ package buffer +import v3 "github.com/deadsy/sdfx/vec/v3" + // Index buffer for a mesh of finite elements. type IB struct { Grid *VoxelGrid } -func NewIB(voxelsX, voxelsY, voxelsZ int) *IB { +func NewIB(voxelsX, voxelsY, voxelsZ int, mins, maxs []v3.Vec) *IB { ib := IB{ - Grid: NewVoxelGrid(voxelsX, voxelsY, voxelsZ), + Grid: NewVoxelGrid(voxelsX, voxelsY, voxelsZ, mins, maxs), } return &ib diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 2b60abfa6..9b52441ae 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -43,6 +43,14 @@ type Voxel struct { max v3.Vec // Max corner of voxel. } +func NewVoxel(min, max v3.Vec) *Voxel { + return &Voxel{ + data: make([]*Element, 0), + min: min, + max: max, + } +} + // Acts like a three-dimensional nested slice using // a one-dimensional slice under the hood. // To increase performance. @@ -51,13 +59,20 @@ type VoxelGrid struct { lenX, lenY, lenZ int // Voxels count in 3 directions. } -func NewVoxelGrid(x, y, z int) *VoxelGrid { - return &VoxelGrid{ +func NewVoxelGrid(x, y, z int, mins, maxs []v3.Vec) *VoxelGrid { + vg := &VoxelGrid{ voxels: make([]*Voxel, x*y*z), lenX: x, lenY: y, lenZ: z, } + + // Assign the min corner and max corner of each voxel. + for i := range vg.voxels { + vg.voxels[i] = NewVoxel(mins[i], maxs[i]) + } + + return vg } func (vg *VoxelGrid) Size() (int, int, int) { diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index f16b18dd3..2b7b4868b 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -22,9 +22,9 @@ type Fem struct { func NewFem(s sdf.SDF3, r render.RenderFE) (*Fem, int) { fes := render.ToFem(s, r) - layersX, layersY, layersZ := r.LayerCounts(s) + voxelsX, voxelsY, voxelsZ, mins, maxs := r.Voxels(s) - m := newFem(layersX, layersY, layersZ) + m := newFem(voxelsX, voxelsY, voxelsZ, mins, maxs) // Fill out the mesh with finite elements. for _, fe := range fes { @@ -33,12 +33,12 @@ func NewFem(s sdf.SDF3, r render.RenderFE) (*Fem, int) { defer m.VBuff.DestroyHashTable() - return m, layersZ + return m, voxelsZ } -func newFem(layersX, layersY, layersZ int) *Fem { +func newFem(layersX, layersY, layersZ int, mins, maxs []v3.Vec) *Fem { return &Fem{ - IBuff: buffer.NewIB(layersX, layersY, layersZ), + IBuff: buffer.NewIB(layersX, layersY, layersZ, mins, maxs), VBuff: buffer.NewVB(), } } diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 560002ac3..565555d59 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -370,7 +370,9 @@ func (inp *Inp) writeBoundary() error { // Write the node IDs. for n := 0; n < len(el.Nodes); n++ { vertex := vertices[n] - isFixedX, isFixedY, isFixedZ := inp.Restraint(vertex.X, vertex.Y, vertex.Z) + // TODO: restraints. + _ = vertex + isFixedX, isFixedY, isFixedZ := false, false, false //inp.Restraint(vertex.X, vertex.Y, vertex.Z) if !isFixedX && !isFixedY && !isFixedZ { continue } diff --git a/render/marchfe.go b/render/marchfe.go index b43fa3df8..80eb027b6 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -5,6 +5,7 @@ import ( "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" + v3 "github.com/deadsy/sdfx/vec/v3" ) //----------------------------------------------------------------------------- @@ -57,8 +58,10 @@ func (r *MarchingCubesFEUniform) Info(s sdf.SDF3) string { return fmt.Sprintf("%dx%dx%d", cells.X, cells.Y, cells.Z) } -// To get the layer counts which are consistent with loops of marching algorithm. -func (r *MarchingCubesFEUniform) LayerCounts(s sdf.SDF3) (int, int, int) { +// Render produces a finite elements mesh over the bounding volume of an sdf3. +// Order and shape of finite elements are selectable. +func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output chan<- []*Fe) { + // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() meshInc := bb0Size.MaxComponent() / float64(r.meshCells) @@ -66,14 +69,14 @@ func (r *MarchingCubesFEUniform) LayerCounts(s sdf.SDF3) (int, int, int) { bb1Size = bb1Size.Ceil().AddScalar(1) bb1Size = bb1Size.MulScalar(meshInc) bb := sdf.NewBox3(bb0.Center(), bb1Size) - size := bb.Size() - steps := conv.V3ToV3i(size.DivScalar(meshInc).Ceil()) - return steps.X, steps.Y, steps.Z + output <- marchingCubesFE(s, bb, meshInc, r.order, r.shape) } -// Render produces a finite elements mesh over the bounding volume of an sdf3. -// Order and shape of finite elements are selectable. -func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output chan<- []*Fe) { +//----------------------------------------------------------------------------- + +// To get the voxel counts and min/max corners which are consistent with loops of marching algorithm. +// This func loops are exactly like `marchingCubesFE` loops. We have to be consistant. +func (r *MarchingCubesFEUniform) Voxels(s sdf.SDF3) (int, int, int, []v3.Vec, []v3.Vec) { // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() @@ -82,7 +85,40 @@ func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output chan<- []*Fe) { bb1Size = bb1Size.Ceil().AddScalar(1) bb1Size = bb1Size.MulScalar(meshInc) bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingCubesFE(s, bb, meshInc, r.order, r.shape) + + size := bb.Size() + base := bb.Min + steps := conv.V3ToV3i(size.DivScalar(meshInc).Ceil()) + inc := size.Div(conv.V3iToV3(steps)) + + nx, ny, nz := steps.X, steps.Y, steps.Z + dx, dy, dz := inc.X, inc.Y, inc.Z + + mins := make([]v3.Vec, 0, nz*nx*ny) + maxs := make([]v3.Vec, 0, nz*nx*ny) + + var p v3.Vec + p.Z = base.Z + for z := 0; z < nz; z++ { + // all cubes in the z and z + 1 layers + p.X = base.X + for x := 0; x < nx; x++ { + p.Y = base.Y + for y := 0; y < ny; y++ { + x0, y0, z0 := p.X, p.Y, p.Z + x1, y1, z1 := x0+dx, y0+dy, z0+dz + + mins = append(mins, v3.Vec{X: x0, Y: y0, Z: z0}) + maxs = append(maxs, v3.Vec{X: x1, Y: y1, Z: z1}) + + p.Y += dy + } + p.X += dx + } + p.Z += dz + } + + return nx, ny, nz, mins, maxs } //----------------------------------------------------------------------------- diff --git a/render/render.go b/render/render.go index e187d1063..038d6a86f 100644 --- a/render/render.go +++ b/render/render.go @@ -13,6 +13,7 @@ import ( "sync" "github.com/deadsy/sdfx/sdf" + v3 "github.com/deadsy/sdfx/vec/v3" ) //----------------------------------------------------------------------------- @@ -33,7 +34,7 @@ type Render2 interface { type RenderFE interface { RenderFE(sdf3 sdf.SDF3, output chan<- []*Fe) Info(sdf3 sdf.SDF3) string - LayerCounts(sdf3 sdf.SDF3) (int, int, int) + Voxels(sdf3 sdf.SDF3) (int, int, int, []v3.Vec, []v3.Vec) } //----------------------------------------------------------------------------- @@ -66,8 +67,8 @@ func ToFem( ) []Fe { fmt.Printf("rendering %s\n", r.Info(s)) - layerCountX, layerCountY, layerCountZ := r.LayerCounts(s) - fmt.Printf("layer counts of marching algorithm are: (%v x %v x %v)\n", layerCountX, layerCountY, layerCountZ) + voxelCountX, voxelCountY, voxelCountZ, _, _ := r.Voxels(s) + fmt.Printf("voxel counts of marching algorithm are: (%v x %v x %v)\n", voxelCountX, voxelCountY, voxelCountZ) // Will be filled by the rendering. fes := make([]Fe, 0) From 83d0984d16fa95935c19efe3f38c817ce407fe4a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 13:23:49 +0330 Subject: [PATCH 577/775] Loops to indetify node ID and voxel of restraints --- render/finiteelements/mesh/inp.go | 7 ++++++- render/finiteelements/mesh/restraint_load.go | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 565555d59..f55034e15 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -85,7 +85,12 @@ func NewInp( // Figure out node and voxel for each restraint. for _, r := range inp.Restraints { - r.FindNode() + r.nodeID, r.voxel = locate(r.Location) + } + + // Figure out node and voxel for each load. + for _, l := range inp.Loads { + l.nodeID, l.voxel = locate(l.Location) } return inp diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index 75ea12d0b..4a994953b 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -43,8 +43,9 @@ func NewLoad(location, magnitude v3.Vec) *Load { } } -// Identify the node to which restraint is applied. +// The closest node is identified. // Also, the containing voxel is figured out. -func (r *Restraint) FindNode() { +func locate(location v3.Vec) (int, v3i.Vec) { // TODO. + return 0, v3i.Vec{} } From 0c5aa92d32a9b2df24f9937de7f8426c2744e670 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 13:27:46 +0330 Subject: [PATCH 578/775] Identify node/voxel by mesh pkg --- render/finiteelements/mesh/fem.go | 8 ++++++++ render/finiteelements/mesh/restraint_load.go | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 2b7b4868b..7cc99b038 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -5,6 +5,7 @@ import ( "github.com/deadsy/sdfx/render/finiteelements/buffer" "github.com/deadsy/sdfx/sdf" v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" ) // Fem is a mesh of finite elements. @@ -76,6 +77,13 @@ func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { m.IBuff.Iterate(f) } +// The closest node is identified. +// Also, the containing voxel is figured out. +func (m *Fem) Locate(location v3.Vec) (int, v3i.Vec) { + // TODO. + return 0, v3i.Vec{} +} + // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. func (m *Fem) WriteInp( path string, diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index 4a994953b..aa588d19b 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -42,10 +42,3 @@ func NewLoad(location, magnitude v3.Vec) *Load { nodeID: 0, } } - -// The closest node is identified. -// Also, the containing voxel is figured out. -func locate(location v3.Vec) (int, v3i.Vec) { - // TODO. - return 0, v3i.Vec{} -} From 2aeb009756194f5a0a28fe1db4137dd68a12b7cc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 13:29:44 +0330 Subject: [PATCH 579/775] Call new methods --- render/finiteelements/mesh/inp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index f55034e15..1e0d8febd 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -85,12 +85,12 @@ func NewInp( // Figure out node and voxel for each restraint. for _, r := range inp.Restraints { - r.nodeID, r.voxel = locate(r.Location) + r.nodeID, r.voxel = inp.Mesh.Locate(r.Location) } // Figure out node and voxel for each load. for _, l := range inp.Loads { - l.nodeID, l.voxel = locate(l.Location) + l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) } return inp From 6994cf4b941428f081a61cfbd5b211e4d4cf9d64 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 13:34:10 +0330 Subject: [PATCH 580/775] Methods for mesh, index buffer, voxel grid --- render/finiteelements/buffer/indexbuffer.go | 11 ++++++++++- render/finiteelements/buffer/voxel.go | 12 +++++++++++- render/finiteelements/mesh/fem.go | 3 +-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index ecfae4b14..c77f69e16 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -1,6 +1,9 @@ package buffer -import v3 "github.com/deadsy/sdfx/vec/v3" +import ( + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" +) // Index buffer for a mesh of finite elements. type IB struct { @@ -31,3 +34,9 @@ func (ib *IB) Iterate(f func(int, int, int, []*Element)) { func (ib *IB) Size() (int, int, int) { return ib.Grid.Size() } + +// The closest node is identified. +// Also, the containing voxel is figured out. +func (ib *IB) Locate(location v3.Vec) (int, v3i.Vec) { + return ib.Grid.Locate(location) +} diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 9b52441ae..dbe3d6285 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -1,6 +1,9 @@ package buffer -import v3 "github.com/deadsy/sdfx/vec/v3" +import ( + v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" +) type Element struct { Nodes []uint32 // Node indices @@ -105,3 +108,10 @@ func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { } } } + +// The closest node is identified. +// Also, the containing voxel is figured out. +func (vg *VoxelGrid) Locate(location v3.Vec) (int, v3i.Vec) { + // TODO. + return 0, v3i.Vec{} +} diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 7cc99b038..c4622055a 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -80,8 +80,7 @@ func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { // The closest node is identified. // Also, the containing voxel is figured out. func (m *Fem) Locate(location v3.Vec) (int, v3i.Vec) { - // TODO. - return 0, v3i.Vec{} + return m.IBuff.Locate(location) } // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. From be2d958fb956db910014b7de05cc4dc299023f6e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 14:38:12 +0330 Subject: [PATCH 581/775] Logic to get node ID & voxel --- render/finiteelements/buffer/voxel.go | 42 +++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index dbe3d6285..7857e74a1 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -1,6 +1,8 @@ package buffer import ( + "math" + v3 "github.com/deadsy/sdfx/vec/v3" "github.com/deadsy/sdfx/vec/v3i" ) @@ -112,6 +114,42 @@ func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { // The closest node is identified. // Also, the containing voxel is figured out. func (vg *VoxelGrid) Locate(location v3.Vec) (int, v3i.Vec) { - // TODO. - return 0, v3i.Vec{} + // Calculating voxel indices. + // Assumes that the voxels are evenly distributed across the grid. + idxX := int((location.X - vg.voxels[0].min.X) / (vg.voxels[0].max.X - vg.voxels[0].min.X) * float64(vg.lenX)) + idxY := int((location.Y - vg.voxels[0].min.Y) / (vg.voxels[0].max.Y - vg.voxels[0].min.Y) * float64(vg.lenY)) + idxZ := int((location.Z - vg.voxels[0].min.Z) / (vg.voxels[0].max.Z - vg.voxels[0].min.Z) * float64(vg.lenZ)) + + // Ensure indices are within bounds + if idxX >= vg.lenX { + idxX = vg.lenX - 1 + } + if idxY >= vg.lenY { + idxY = vg.lenY - 1 + } + if idxZ >= vg.lenZ { + idxZ = vg.lenZ - 1 + } + + // Get elements in the voxel + elements := vg.Get(idxX, idxY, idxZ) + + // Find the closest node + closestNode := -1 + minDistance := math.Inf(1) + + for _, element := range elements { + for _, node := range element.Nodes { + // Assuming you have a function that gives you the position of a node + nodePos := GetNodePosition(node) + + distance := location.Sub(nodePos).Length() + if distance < minDistance { + minDistance = distance + closestNode = int(node) + } + } + } + + return closestNode, v3i.Vec{X: idxX, Y: idxY, Z: idxZ} } From 98ebde8b6589e07d8143c5e5aaa7545f13518a21 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 14:53:44 +0330 Subject: [PATCH 582/775] Change logic location due to var access limits --- render/finiteelements/buffer/indexbuffer.go | 7 -- render/finiteelements/buffer/voxel.go | 84 +++++---------------- render/finiteelements/mesh/fem.go | 43 ++++++++++- 3 files changed, 61 insertions(+), 73 deletions(-) diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index c77f69e16..378ffe6e4 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -2,7 +2,6 @@ package buffer import ( v3 "github.com/deadsy/sdfx/vec/v3" - "github.com/deadsy/sdfx/vec/v3i" ) // Index buffer for a mesh of finite elements. @@ -34,9 +33,3 @@ func (ib *IB) Iterate(f func(int, int, int, []*Element)) { func (ib *IB) Size() (int, int, int) { return ib.Grid.Size() } - -// The closest node is identified. -// Also, the containing voxel is figured out. -func (ib *IB) Locate(location v3.Vec) (int, v3i.Vec) { - return ib.Grid.Locate(location) -} diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 7857e74a1..7db524536 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -1,10 +1,7 @@ package buffer import ( - "math" - v3 "github.com/deadsy/sdfx/vec/v3" - "github.com/deadsy/sdfx/vec/v3i" ) type Element struct { @@ -44,15 +41,15 @@ func NewElement(nodes []uint32) *Element { type Voxel struct { data []*Element // Each voxel stores multiple elements. - min v3.Vec // Min corner of voxel. - max v3.Vec // Max corner of voxel. + Min v3.Vec // Min corner of voxel. + Max v3.Vec // Max corner of voxel. } func NewVoxel(min, max v3.Vec) *Voxel { return &Voxel{ data: make([]*Element, 0), - min: min, - max: max, + Min: min, + Max: max, } } @@ -60,96 +57,53 @@ func NewVoxel(min, max v3.Vec) *Voxel { // a one-dimensional slice under the hood. // To increase performance. type VoxelGrid struct { - voxels []*Voxel // - lenX, lenY, lenZ int // Voxels count in 3 directions. + Voxels []*Voxel // + LenX, LenY, LenZ int // Voxels count in 3 directions. } func NewVoxelGrid(x, y, z int, mins, maxs []v3.Vec) *VoxelGrid { vg := &VoxelGrid{ - voxels: make([]*Voxel, x*y*z), - lenX: x, - lenY: y, - lenZ: z, + Voxels: make([]*Voxel, x*y*z), + LenX: x, + LenY: y, + LenZ: z, } // Assign the min corner and max corner of each voxel. - for i := range vg.voxels { - vg.voxels[i] = NewVoxel(mins[i], maxs[i]) + for i := range vg.Voxels { + vg.Voxels[i] = NewVoxel(mins[i], maxs[i]) } return vg } func (vg *VoxelGrid) Size() (int, int, int) { - return vg.lenX, vg.lenY, vg.lenZ + return vg.LenX, vg.LenY, vg.LenZ } // To get all the elements inside a voxel. func (vg *VoxelGrid) Get(x, y, z int) []*Element { - return vg.voxels[x*vg.lenY*vg.lenZ+y*vg.lenZ+z].data + return vg.Voxels[x*vg.LenY*vg.LenZ+y*vg.LenZ+z].data } // To set all the elements inside a voxel at once. func (vg *VoxelGrid) Set(x, y, z int, value []*Element) { - vg.voxels[x*vg.lenY*vg.lenZ+y*vg.lenZ+z].data = value + vg.Voxels[x*vg.LenY*vg.LenZ+y*vg.LenZ+z].data = value } // To append a single element to the elements inside a voxel. func (vg *VoxelGrid) Append(x, y, z int, value *Element) { - vg.voxels[x*vg.lenY*vg.lenZ+y*vg.lenZ+z].data = append(vg.voxels[x*vg.lenY*vg.lenZ+y*vg.lenZ+z].data, value) + vg.Voxels[x*vg.LenY*vg.LenZ+y*vg.LenZ+z].data = append(vg.Voxels[x*vg.LenY*vg.LenZ+y*vg.LenZ+z].data, value) } // To iterate over all voxels and get elements inside each voxel and do stuff with them. func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { - for z := 0; z < vg.lenZ; z++ { - for y := 0; y < vg.lenY; y++ { - for x := 0; x < vg.lenX; x++ { + for z := 0; z < vg.LenZ; z++ { + for y := 0; y < vg.LenY; y++ { + for x := 0; x < vg.LenX; x++ { value := vg.Get(x, y, z) f(x, y, z, value) } } } } - -// The closest node is identified. -// Also, the containing voxel is figured out. -func (vg *VoxelGrid) Locate(location v3.Vec) (int, v3i.Vec) { - // Calculating voxel indices. - // Assumes that the voxels are evenly distributed across the grid. - idxX := int((location.X - vg.voxels[0].min.X) / (vg.voxels[0].max.X - vg.voxels[0].min.X) * float64(vg.lenX)) - idxY := int((location.Y - vg.voxels[0].min.Y) / (vg.voxels[0].max.Y - vg.voxels[0].min.Y) * float64(vg.lenY)) - idxZ := int((location.Z - vg.voxels[0].min.Z) / (vg.voxels[0].max.Z - vg.voxels[0].min.Z) * float64(vg.lenZ)) - - // Ensure indices are within bounds - if idxX >= vg.lenX { - idxX = vg.lenX - 1 - } - if idxY >= vg.lenY { - idxY = vg.lenY - 1 - } - if idxZ >= vg.lenZ { - idxZ = vg.lenZ - 1 - } - - // Get elements in the voxel - elements := vg.Get(idxX, idxY, idxZ) - - // Find the closest node - closestNode := -1 - minDistance := math.Inf(1) - - for _, element := range elements { - for _, node := range element.Nodes { - // Assuming you have a function that gives you the position of a node - nodePos := GetNodePosition(node) - - distance := location.Sub(nodePos).Length() - if distance < minDistance { - minDistance = distance - closestNode = int(node) - } - } - } - - return closestNode, v3i.Vec{X: idxX, Y: idxY, Z: idxZ} -} diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index c4622055a..c203c84d1 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -1,6 +1,8 @@ package mesh import ( + "math" + "github.com/deadsy/sdfx/render" "github.com/deadsy/sdfx/render/finiteelements/buffer" "github.com/deadsy/sdfx/sdf" @@ -79,8 +81,47 @@ func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { // The closest node is identified. // Also, the containing voxel is figured out. +// +// This logic has to be here, since we need access to any node vertex. func (m *Fem) Locate(location v3.Vec) (int, v3i.Vec) { - return m.IBuff.Locate(location) + // Calculating voxel indices. + // Assumes that the voxels are evenly distributed across the grid. + idxX := int((location.X - m.IBuff.Grid.Voxels[0].Min.X) / (m.IBuff.Grid.Voxels[0].Max.X - m.IBuff.Grid.Voxels[0].Min.X) * float64(m.IBuff.Grid.LenX)) + idxY := int((location.Y - m.IBuff.Grid.Voxels[0].Min.Y) / (m.IBuff.Grid.Voxels[0].Max.Y - m.IBuff.Grid.Voxels[0].Min.Y) * float64(m.IBuff.Grid.LenY)) + idxZ := int((location.Z - m.IBuff.Grid.Voxels[0].Min.Z) / (m.IBuff.Grid.Voxels[0].Max.Z - m.IBuff.Grid.Voxels[0].Min.Z) * float64(m.IBuff.Grid.LenZ)) + + // Ensure indices are within bounds + if idxX >= m.IBuff.Grid.LenX { + idxX = m.IBuff.Grid.LenX - 1 + } + if idxY >= m.IBuff.Grid.LenY { + idxY = m.IBuff.Grid.LenY - 1 + } + if idxZ >= m.IBuff.Grid.LenZ { + idxZ = m.IBuff.Grid.LenZ - 1 + } + + // Get elements in the voxel + elements := m.IBuff.Grid.Get(idxX, idxY, idxZ) + + // Find the closest node + closestNode := -1 + minDistance := math.Inf(1) + + for _, element := range elements { + for _, node := range element.Nodes { + // A function that gives you the position of a node. + nodePos := m.vertex(node) + + distance := location.Sub(nodePos).Length() + if distance < minDistance { + minDistance = distance + closestNode = int(node) + } + } + } + + return closestNode, v3i.Vec{X: idxX, Y: idxY, Z: idxZ} } // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. From e68b3b3e9f7ad4eba2fd792277a70eb763bee916 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 15:09:16 +0330 Subject: [PATCH 583/775] Write boundary to file according to new logic --- render/finiteelements/mesh/inp.go | 121 +++++++++++++----------------- 1 file changed, 54 insertions(+), 67 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 1e0d8febd..b00fb0cc4 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -363,80 +363,67 @@ func (inp *Inp) writeBoundary() error { return err } - process := func(x, y, z int, els []*buffer.Element) { - for _, el := range els { - vertices := make([]v3.Vec, len(el.Nodes)) - ids := make([]uint32, len(el.Nodes)) - for n := 0; n < len(el.Nodes); n++ { - vertices[n] = inp.Mesh.vertex(el.Nodes[n]) - ids[n] = inp.TempVBuff.Id(vertices[n]) - } - - // Write the node IDs. - for n := 0; n < len(el.Nodes); n++ { - vertex := vertices[n] - // TODO: restraints. - _ = vertex - isFixedX, isFixedY, isFixedZ := false, false, false //inp.Restraint(vertex.X, vertex.Y, vertex.Z) - if !isFixedX && !isFixedY && !isFixedZ { - continue - } + // The closest node to any restraint is already computed. + for _, r := range inp.Restraints { + isFixedX, isFixedY, isFixedZ := r.IsFixedX, r.IsFixedY, r.IsFixedZ + if !isFixedX && !isFixedY && !isFixedZ { + continue + } - // ID starts from one not zero. + id := r.nodeID - // To be written: - // 1) Node number/ID. - // 2) First degree of freedom constrained. - // 3) Last degree of freedom constrained. This field may be left blank if only - // one degree of freedom is constrained. + // To be written: + // + // 1) Node ID. + // 2) First degree of freedom constrained. + // 3) Last degree of freedom constrained. This field may be left blank if only + // one degree of freedom is constrained. + // + // Note: written node ID would start from one not zero. - if isFixedX && isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if isFixedX && isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1,2\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if !isFixedX && isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,2,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if isFixedX && !isFixedY && isFixedZ { - // TODO: Can we write this case by just one line, not two lines? - _, err = f.WriteString(fmt.Sprintf("%d,1\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - _, err = f.WriteString(fmt.Sprintf("%d,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if isFixedX && !isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if !isFixedX && isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,2\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } else if !isFixedX && !isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,3\n", ids[n]+1)) - if err != nil { - panic("Couldn't write boundary to file: " + err.Error()) - } - } + if isFixedX && isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1,2\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,2,3\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && !isFixedY && isFixedZ { + // TODO: Can we write this case by just one line, not two lines? + _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,3\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if isFixedX && !isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && isFixedY && !isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,2\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + } else if !isFixedX && !isFixedY && isFixedZ { + _, err = f.WriteString(fmt.Sprintf("%d,3\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) } } } - inp.Mesh.iterate(process) - return nil } From 4fe8833aaf0e7c3e94dbe63b357077a3bbdc87ab Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 16 Jul 2023 15:46:15 +0330 Subject: [PATCH 584/775] Change location of logic --- render/finiteelements/mesh/inp.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index b00fb0cc4..347bb197b 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -83,12 +83,8 @@ func NewInp( GravityMagnitude: gravityMagnitude, } - // Figure out node and voxel for each restraint. - for _, r := range inp.Restraints { - r.nodeID, r.voxel = inp.Mesh.Locate(r.Location) - } - // Figure out node and voxel for each load. + // TODO: move this statement to the logic that writes loads to file. for _, l := range inp.Loads { l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) } @@ -363,6 +359,11 @@ func (inp *Inp) writeBoundary() error { return err } + // Figure out node and voxel for each restraint. + for _, r := range inp.Restraints { + r.nodeID, r.voxel = inp.Mesh.Locate(r.Location) + } + // The closest node to any restraint is already computed. for _, r := range inp.Restraints { isFixedX, isFixedY, isFixedZ := r.IsFixedX, r.IsFixedY, r.IsFixedZ From 1844e7a72a702e4dba3e0d3835095ec20a5c5541 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 17 Jul 2023 10:04:28 +0330 Subject: [PATCH 585/775] Set voxel dimensions explicitly --- render/finiteelements/buffer/indexbuffer.go | 5 ++-- render/finiteelements/buffer/voxel.go | 29 +++++++++++---------- render/finiteelements/mesh/fem.go | 28 ++++++++++---------- render/marchfe.go | 7 ++--- render/render.go | 7 ++--- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index 378ffe6e4..8eb48de7e 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -2,6 +2,7 @@ package buffer import ( v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" ) // Index buffer for a mesh of finite elements. @@ -9,9 +10,9 @@ type IB struct { Grid *VoxelGrid } -func NewIB(voxelsX, voxelsY, voxelsZ int, mins, maxs []v3.Vec) *IB { +func NewIB(voxelLen v3i.Vec, voxelDim v3.Vec, mins, maxs []v3.Vec) *IB { ib := IB{ - Grid: NewVoxelGrid(voxelsX, voxelsY, voxelsZ, mins, maxs), + Grid: NewVoxelGrid(voxelLen, voxelDim, mins, maxs), } return &ib diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 7db524536..8f1de8e36 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -2,6 +2,7 @@ package buffer import ( v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" ) type Element struct { @@ -57,16 +58,16 @@ func NewVoxel(min, max v3.Vec) *Voxel { // a one-dimensional slice under the hood. // To increase performance. type VoxelGrid struct { - Voxels []*Voxel // - LenX, LenY, LenZ int // Voxels count in 3 directions. + Voxels []*Voxel // + Len v3i.Vec // Voxel count in 3 directions. + Dim v3.Vec // Voxel dimension in 3 directions. } -func NewVoxelGrid(x, y, z int, mins, maxs []v3.Vec) *VoxelGrid { +func NewVoxelGrid(len v3i.Vec, dim v3.Vec, mins, maxs []v3.Vec) *VoxelGrid { vg := &VoxelGrid{ - Voxels: make([]*Voxel, x*y*z), - LenX: x, - LenY: y, - LenZ: z, + Voxels: make([]*Voxel, len.X*len.Y*len.Z), + Len: len, + Dim: dim, } // Assign the min corner and max corner of each voxel. @@ -78,29 +79,29 @@ func NewVoxelGrid(x, y, z int, mins, maxs []v3.Vec) *VoxelGrid { } func (vg *VoxelGrid) Size() (int, int, int) { - return vg.LenX, vg.LenY, vg.LenZ + return vg.Len.X, vg.Len.Y, vg.Len.Z } // To get all the elements inside a voxel. func (vg *VoxelGrid) Get(x, y, z int) []*Element { - return vg.Voxels[x*vg.LenY*vg.LenZ+y*vg.LenZ+z].data + return vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data } // To set all the elements inside a voxel at once. func (vg *VoxelGrid) Set(x, y, z int, value []*Element) { - vg.Voxels[x*vg.LenY*vg.LenZ+y*vg.LenZ+z].data = value + vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data = value } // To append a single element to the elements inside a voxel. func (vg *VoxelGrid) Append(x, y, z int, value *Element) { - vg.Voxels[x*vg.LenY*vg.LenZ+y*vg.LenZ+z].data = append(vg.Voxels[x*vg.LenY*vg.LenZ+y*vg.LenZ+z].data, value) + vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data = append(vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data, value) } // To iterate over all voxels and get elements inside each voxel and do stuff with them. func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { - for z := 0; z < vg.LenZ; z++ { - for y := 0; y < vg.LenY; y++ { - for x := 0; x < vg.LenX; x++ { + for z := 0; z < vg.Len.Z; z++ { + for y := 0; y < vg.Len.Y; y++ { + for x := 0; x < vg.Len.X; x++ { value := vg.Get(x, y, z) f(x, y, z, value) } diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index c203c84d1..10306dc2f 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -25,9 +25,9 @@ type Fem struct { func NewFem(s sdf.SDF3, r render.RenderFE) (*Fem, int) { fes := render.ToFem(s, r) - voxelsX, voxelsY, voxelsZ, mins, maxs := r.Voxels(s) + voxelLen, voxelDim, mins, maxs := r.Voxels(s) - m := newFem(voxelsX, voxelsY, voxelsZ, mins, maxs) + m := newFem(voxelLen, voxelDim, mins, maxs) // Fill out the mesh with finite elements. for _, fe := range fes { @@ -36,12 +36,12 @@ func NewFem(s sdf.SDF3, r render.RenderFE) (*Fem, int) { defer m.VBuff.DestroyHashTable() - return m, voxelsZ + return m, voxelLen.Z } -func newFem(layersX, layersY, layersZ int, mins, maxs []v3.Vec) *Fem { +func newFem(voxelLen v3i.Vec, voxelDim v3.Vec, mins, maxs []v3.Vec) *Fem { return &Fem{ - IBuff: buffer.NewIB(layersX, layersY, layersZ, mins, maxs), + IBuff: buffer.NewIB(voxelLen, voxelDim, mins, maxs), VBuff: buffer.NewVB(), } } @@ -86,19 +86,19 @@ func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { func (m *Fem) Locate(location v3.Vec) (int, v3i.Vec) { // Calculating voxel indices. // Assumes that the voxels are evenly distributed across the grid. - idxX := int((location.X - m.IBuff.Grid.Voxels[0].Min.X) / (m.IBuff.Grid.Voxels[0].Max.X - m.IBuff.Grid.Voxels[0].Min.X) * float64(m.IBuff.Grid.LenX)) - idxY := int((location.Y - m.IBuff.Grid.Voxels[0].Min.Y) / (m.IBuff.Grid.Voxels[0].Max.Y - m.IBuff.Grid.Voxels[0].Min.Y) * float64(m.IBuff.Grid.LenY)) - idxZ := int((location.Z - m.IBuff.Grid.Voxels[0].Min.Z) / (m.IBuff.Grid.Voxels[0].Max.Z - m.IBuff.Grid.Voxels[0].Min.Z) * float64(m.IBuff.Grid.LenZ)) + idxX := int((location.X - m.IBuff.Grid.Voxels[0].Min.X) / (m.IBuff.Grid.Voxels[0].Max.X - m.IBuff.Grid.Voxels[0].Min.X) * float64(m.IBuff.Grid.Len.X)) + idxY := int((location.Y - m.IBuff.Grid.Voxels[0].Min.Y) / (m.IBuff.Grid.Voxels[0].Max.Y - m.IBuff.Grid.Voxels[0].Min.Y) * float64(m.IBuff.Grid.Len.Y)) + idxZ := int((location.Z - m.IBuff.Grid.Voxels[0].Min.Z) / (m.IBuff.Grid.Voxels[0].Max.Z - m.IBuff.Grid.Voxels[0].Min.Z) * float64(m.IBuff.Grid.Len.Z)) // Ensure indices are within bounds - if idxX >= m.IBuff.Grid.LenX { - idxX = m.IBuff.Grid.LenX - 1 + if idxX >= m.IBuff.Grid.Len.X { + idxX = m.IBuff.Grid.Len.X - 1 } - if idxY >= m.IBuff.Grid.LenY { - idxY = m.IBuff.Grid.LenY - 1 + if idxY >= m.IBuff.Grid.Len.Y { + idxY = m.IBuff.Grid.Len.Y - 1 } - if idxZ >= m.IBuff.Grid.LenZ { - idxZ = m.IBuff.Grid.LenZ - 1 + if idxZ >= m.IBuff.Grid.Len.Z { + idxZ = m.IBuff.Grid.Len.Z - 1 } // Get elements in the voxel diff --git a/render/marchfe.go b/render/marchfe.go index 80eb027b6..af73b73ff 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -6,6 +6,7 @@ import ( "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" ) //----------------------------------------------------------------------------- @@ -74,9 +75,9 @@ func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output chan<- []*Fe) { //----------------------------------------------------------------------------- -// To get the voxel counts and min/max corners which are consistent with loops of marching algorithm. +// To get the voxel count, dimension, and min/max corner which are consistent with loops of marching algorithm. // This func loops are exactly like `marchingCubesFE` loops. We have to be consistant. -func (r *MarchingCubesFEUniform) Voxels(s sdf.SDF3) (int, int, int, []v3.Vec, []v3.Vec) { +func (r *MarchingCubesFEUniform) Voxels(s sdf.SDF3) (v3i.Vec, v3.Vec, []v3.Vec, []v3.Vec) { // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() @@ -118,7 +119,7 @@ func (r *MarchingCubesFEUniform) Voxels(s sdf.SDF3) (int, int, int, []v3.Vec, [] p.Z += dz } - return nx, ny, nz, mins, maxs + return v3i.Vec{X: nx, Y: ny, Z: nz}, v3.Vec{X: dx, Y: dy, Z: dz}, mins, maxs } //----------------------------------------------------------------------------- diff --git a/render/render.go b/render/render.go index 038d6a86f..ae3c356ec 100644 --- a/render/render.go +++ b/render/render.go @@ -14,6 +14,7 @@ import ( "github.com/deadsy/sdfx/sdf" v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" ) //----------------------------------------------------------------------------- @@ -34,7 +35,7 @@ type Render2 interface { type RenderFE interface { RenderFE(sdf3 sdf.SDF3, output chan<- []*Fe) Info(sdf3 sdf.SDF3) string - Voxels(sdf3 sdf.SDF3) (int, int, int, []v3.Vec, []v3.Vec) + Voxels(sdf3 sdf.SDF3) (v3i.Vec, v3.Vec, []v3.Vec, []v3.Vec) } //----------------------------------------------------------------------------- @@ -67,8 +68,8 @@ func ToFem( ) []Fe { fmt.Printf("rendering %s\n", r.Info(s)) - voxelCountX, voxelCountY, voxelCountZ, _, _ := r.Voxels(s) - fmt.Printf("voxel counts of marching algorithm are: (%v x %v x %v)\n", voxelCountX, voxelCountY, voxelCountZ) + voxelCount, _, _, _ := r.Voxels(s) + fmt.Printf("voxel counts of marching algorithm are: (%v x %v x %v)\n", voxelCount.X, voxelCount.Y, voxelCount.Z) // Will be filled by the rendering. fes := make([]Fe, 0) From a992076149f3de35bd3060f3292100ea6f353ba6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 17 Jul 2023 10:36:07 +0330 Subject: [PATCH 586/775] Fix bug? How voxel index is computed --- render/finiteelements/mesh/fem.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 10306dc2f..e7b566809 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -85,10 +85,9 @@ func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { // This logic has to be here, since we need access to any node vertex. func (m *Fem) Locate(location v3.Vec) (int, v3i.Vec) { // Calculating voxel indices. - // Assumes that the voxels are evenly distributed across the grid. - idxX := int((location.X - m.IBuff.Grid.Voxels[0].Min.X) / (m.IBuff.Grid.Voxels[0].Max.X - m.IBuff.Grid.Voxels[0].Min.X) * float64(m.IBuff.Grid.Len.X)) - idxY := int((location.Y - m.IBuff.Grid.Voxels[0].Min.Y) / (m.IBuff.Grid.Voxels[0].Max.Y - m.IBuff.Grid.Voxels[0].Min.Y) * float64(m.IBuff.Grid.Len.Y)) - idxZ := int((location.Z - m.IBuff.Grid.Voxels[0].Min.Z) / (m.IBuff.Grid.Voxels[0].Max.Z - m.IBuff.Grid.Voxels[0].Min.Z) * float64(m.IBuff.Grid.Len.Z)) + idxX := int(math.Floor((location.X - m.IBuff.Grid.Voxels[0].Min.X) / (m.IBuff.Grid.Dim.X))) + idxY := int(math.Floor((location.Y - m.IBuff.Grid.Voxels[0].Min.Y) / (m.IBuff.Grid.Dim.Y))) + idxZ := int(math.Floor((location.Z - m.IBuff.Grid.Voxels[0].Min.Z) / (m.IBuff.Grid.Dim.Z))) // Ensure indices are within bounds if idxX >= m.IBuff.Grid.Len.X { From dfe651badbfc484499e12b5a3635a2b1e81e5606 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 17 Jul 2023 11:39:29 +0330 Subject: [PATCH 587/775] Fix: node ID: original VB against temp VB --- render/finiteelements/mesh/fem.go | 6 +++--- render/finiteelements/mesh/inp.go | 5 ++++- render/finiteelements/mesh/restraint_load.go | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index e7b566809..288d981da 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -83,7 +83,7 @@ func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { // Also, the containing voxel is figured out. // // This logic has to be here, since we need access to any node vertex. -func (m *Fem) Locate(location v3.Vec) (int, v3i.Vec) { +func (m *Fem) Locate(location v3.Vec) (uint32, v3i.Vec) { // Calculating voxel indices. idxX := int(math.Floor((location.X - m.IBuff.Grid.Voxels[0].Min.X) / (m.IBuff.Grid.Dim.X))) idxY := int(math.Floor((location.Y - m.IBuff.Grid.Voxels[0].Min.Y) / (m.IBuff.Grid.Dim.Y))) @@ -104,7 +104,7 @@ func (m *Fem) Locate(location v3.Vec) (int, v3i.Vec) { elements := m.IBuff.Grid.Get(idxX, idxY, idxZ) // Find the closest node - closestNode := -1 + var closestNode uint32 minDistance := math.Inf(1) for _, element := range elements { @@ -115,7 +115,7 @@ func (m *Fem) Locate(location v3.Vec) (int, v3i.Vec) { distance := location.Sub(nodePos).Length() if distance < minDistance { minDistance = distance - closestNode = int(node) + closestNode = node } } } diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 347bb197b..6c3143659 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -371,7 +371,10 @@ func (inp *Inp) writeBoundary() error { continue } - id := r.nodeID + // Node ID should be consistant with the temp vertex buffer. + // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. + vertex := inp.Mesh.vertex(r.nodeID) + id := inp.TempVBuff.Id(vertex) // To be written: // diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index aa588d19b..228eaabeb 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -12,7 +12,7 @@ type Restraint struct { IsFixedY bool // Is Y degree of freedom fixed? IsFixedZ bool // Is Z degree of freedom fixed? voxel v3i.Vec // Containing voxel: to be computed by logic. - nodeID int // Eventual node to which the restraint is applied. To be computed. + nodeID uint32 // Eventual node to which the restraint is applied. To be computed. } // Point loads are applied to the nodes of the mesh. @@ -20,7 +20,7 @@ type Load struct { Location v3.Vec // Exact coordinate. Magnitude v3.Vec // X, Y, Z magnitude. voxel v3i.Vec // Containing voxel: to be computed by logic. - nodeID int // Eventual node to which the load is applied. To be computed. + nodeID uint32 // Eventual node to which the load is applied. To be computed. } func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { From 4b7a30788cc5717623fe5fd2a60f289372a51ae0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 17 Jul 2023 14:21:36 +0330 Subject: [PATCH 588/775] Logic to write point load to `inp` file --- examples/finite_elements/main.go | 5 ++- render/finiteelements/mesh/inp.go | 64 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index ef67b73a0..51793fbdc 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -55,8 +55,11 @@ func main() { mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), mesh.NewRestraint(v3.Vec{X: 200, Y: 17.32, Z: 0}, false, true, true), } + // Gravity load is used for benchmarks. So, there is no point load. - loads := []*mesh.Load{} + loads := []*mesh.Load{ + mesh.NewLoad(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 0, Z: 0}), + } switch benchmark { case Square: diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 6c3143659..a796314af 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -27,6 +27,8 @@ type Inp struct { PathElsC3D20R string // For writing boundary conditions to a separate file. PathBou string + // For writing loads to a separate file. + PathLoad string // Output `inp` file would include start layer. LayerStart int // Output `inp` file would exclude end layer. @@ -71,6 +73,7 @@ func NewInp( PathElsC3D8: path + ".elements_C3D8", PathElsC3D20R: path + ".elements_C3D20R", PathBou: path + ".boundary", + PathLoad: path + ".load", LayerStart: layerStart, LayerEnd: layerEnd, TempVBuff: buffer.NewVB(), @@ -162,6 +165,17 @@ func (inp *Inp) Write() error { return err } + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathLoad)) + if err != nil { + return err + } + + err = inp.writeLoad() + if err != nil { + return err + } + return inp.writeFooter(f) } @@ -431,6 +445,56 @@ func (inp *Inp) writeBoundary() error { return nil } +func (inp *Inp) writeLoad() error { + // Write to a separate file to avoid cluttering the `inp` file. + f, err := os.Create(inp.PathLoad) + if err != nil { + return err + } + defer f.Close() + + _, err = f.WriteString("*CLOAD\n") + if err != nil { + return err + } + + // Figure out node and voxel for each. + for _, l := range inp.Loads { + l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) + } + + // The closest node to any restraint is already computed. + for _, l := range inp.Loads { + // Node ID should be consistant with the temp vertex buffer. + // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. + vertex := inp.Mesh.vertex(l.nodeID) + id := inp.TempVBuff.Id(vertex) + + // To be written: + // + // 1) Node ID. + // 2) Degree of freedom. + // 3) Magnitude of the load. + // + // Note: written node ID would start from one not zero. + + _, err = f.WriteString(fmt.Sprintf("%d,1,%f\n", id+1, l.Magnitude.X)) + if err != nil { + panic("Couldn't write load to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,2,%f\n", id+1, l.Magnitude.Y)) + if err != nil { + panic("Couldn't write load to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,3,%f\n", id+1, l.Magnitude.Z)) + if err != nil { + panic("Couldn't write load to file: " + err.Error()) + } + } + + return nil +} + func (inp *Inp) writeFooter(f *os.File) error { // Define material. From fbc25b46c2d919dd48016f1e385c90c67a0979d5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 17 Jul 2023 14:35:31 +0330 Subject: [PATCH 589/775] Fix: `*CLOAD` should only be used within a STEP --- render/finiteelements/mesh/inp.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index a796314af..a5b7296a9 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -165,17 +165,6 @@ func (inp *Inp) Write() error { return err } - // Include a separate file to avoid cluttering the `inp` file. - _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathLoad)) - if err != nil { - return err - } - - err = inp.writeLoad() - if err != nil { - return err - } - return inp.writeFooter(f) } @@ -551,6 +540,19 @@ func (inp *Inp) writeFooter(f *os.File) error { return err } + // Write point loads. + + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathLoad)) + if err != nil { + return err + } + + err = inp.writeLoad() + if err != nil { + return err + } + // Write distributed loads. _, err = f.WriteString("*DLOAD\n") From f58671a5e2669a905654b0cc8114616ec86ed254 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 17 Jul 2023 16:17:09 +0330 Subject: [PATCH 590/775] Multiple restraints on edge --- examples/finite_elements/main.go | 33 ++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 51793fbdc..ce4e0b4c0 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -49,12 +49,8 @@ func main() { benchmark = Benchmark(bmint) } - restraints := []*mesh.Restraint{ - mesh.NewRestraint(v3.Vec{X: 0, Y: 0, Z: 0}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: 17.32, Z: 0}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 17.32, Z: 0}, false, true, true), - } + // To be set for each benchmark. + var restraints []*mesh.Restraint // Gravity load is used for benchmarks. So, there is no point load. loads := []*mesh.Load{ @@ -63,6 +59,7 @@ func main() { switch benchmark { case Square: + restraints = benchmarkSquareRestraint() benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraints, loads) case Circle: benchmarkRun("../../files/benchmark-circle.stl", 50, 0, 3, restraints, loads) @@ -240,3 +237,27 @@ func dilationErosion(s sdf.SDF3) sdf.SDF3 { return erosion } + +func benchmarkSquareRestraint() []*mesh.Restraint { + // Four corners. + restraints := []*mesh.Restraint{ + mesh.NewRestraint(v3.Vec{X: 0, Y: 0, Z: 0}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: 17.32, Z: 0}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 17.32, Z: 0}, false, true, true), + } + + // Let's avoid stress concentration by increasing the number of restraints. + // Let's increase it so that most of the edge length is restrained. Not just corners. + gap := 0.1 + maxY := 17.32 + for i := 0; i < int(maxY); i++ { + restraints = append(restraints, mesh.NewRestraint(v3.Vec{X: 0, Y: float64(i * int(gap)), Z: 0}, true, true, true)) + } + + for i := 0; i < int(maxY); i++ { + restraints = append(restraints, mesh.NewRestraint(v3.Vec{X: 200, Y: float64(i * int(gap)), Z: 0}, false, true, true)) + } + + return restraints +} From ac02adc1fe08614c84b91da91d01819302c9eddb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 17 Jul 2023 16:25:28 +0330 Subject: [PATCH 591/775] Fix bug? Fix loop? Simplify. --- examples/finite_elements/main.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index ce4e0b4c0..2019cfefb 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -249,14 +249,17 @@ func benchmarkSquareRestraint() []*mesh.Restraint { // Let's avoid stress concentration by increasing the number of restraints. // Let's increase it so that most of the edge length is restrained. Not just corners. - gap := 0.1 - maxY := 17.32 - for i := 0; i < int(maxY); i++ { - restraints = append(restraints, mesh.NewRestraint(v3.Vec{X: 0, Y: float64(i * int(gap)), Z: 0}, true, true, true)) + gap := 1.0 + var y float64 + for y <= 17.32 { + restraints = append(restraints, mesh.NewRestraint(v3.Vec{X: 0, Y: y, Z: 0}, true, true, true)) + y += gap } - for i := 0; i < int(maxY); i++ { - restraints = append(restraints, mesh.NewRestraint(v3.Vec{X: 200, Y: float64(i * int(gap)), Z: 0}, false, true, true)) + y = 0 + for y <= 17.32 { + restraints = append(restraints, mesh.NewRestraint(v3.Vec{X: 200, Y: y, Z: 0}, false, true, true)) + y += gap } return restraints From 8a4af59b1b00d56bef344904db3f221a734f58ee Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 18 Jul 2023 13:50:28 +0330 Subject: [PATCH 592/775] Set the roller restraints for circle benchmark --- examples/finite_elements/main.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 2019cfefb..69a284133 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -62,6 +62,7 @@ func main() { restraints = benchmarkSquareRestraint() benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraints, loads) case Circle: + restraints = benchmarkCircleRestraint() benchmarkRun("../../files/benchmark-circle.stl", 50, 0, 3, restraints, loads) case Pipe: benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads) @@ -264,3 +265,25 @@ func benchmarkSquareRestraint() []*mesh.Restraint { return restraints } + +func benchmarkCircleRestraint() []*mesh.Restraint { + // Four corners. + restraints := []*mesh.Restraint{ + mesh.NewRestraint(v3.Vec{X: 0, Y: 0, Z: 0}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: -2.0313, Z: 0.213498}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: -3.97382, Z: 0.844661}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: -5.74266, Z: 1.8659}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: -7.26052, Z: 3.23259}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: -8.46107, Z: 4.885}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: -9.29182, Z: 6.7509}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 2.0313, Z: 0.213498}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 3.97382, Z: 0.844661}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 5.74266, Z: 1.8659}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 7.26052, Z: 3.23259}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 8.46107, Z: 4.885}, false, true, true), + mesh.NewRestraint(v3.Vec{X: 200, Y: 9.29182, Z: 6.7509}, false, true, true), + } + + return restraints +} From 62304323f4d4d61cd3fcc14b28161e2aeddada3b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 18 Jul 2023 13:59:25 +0330 Subject: [PATCH 593/775] Restraints for the pinnned end --- examples/finite_elements/main.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 69a284133..99f555046 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -267,9 +267,23 @@ func benchmarkSquareRestraint() []*mesh.Restraint { } func benchmarkCircleRestraint() []*mesh.Restraint { - // Four corners. restraints := []*mesh.Restraint{ + // The pinned end of 3D beam. mesh.NewRestraint(v3.Vec{X: 0, Y: 0, Z: 0}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: -2.0313, Z: 0.213498}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: -3.97382, Z: 0.844661}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: -5.74266, Z: 1.8659}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: -7.26052, Z: 3.23259}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: -8.46107, Z: 4.885}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: -9.29182, Z: 6.7509}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: 2.0313, Z: 0.213498}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: 3.97382, Z: 0.844661}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: 5.74266, Z: 1.8659}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: 7.26052, Z: 3.23259}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: 8.46107, Z: 4.885}, true, true, true), + mesh.NewRestraint(v3.Vec{X: 0, Y: 9.29182, Z: 6.7509}, true, true, true), + + // The roller end of 3D beam. mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), mesh.NewRestraint(v3.Vec{X: 200, Y: -2.0313, Z: 0.213498}, false, true, true), mesh.NewRestraint(v3.Vec{X: 200, Y: -3.97382, Z: 0.844661}, false, true, true), From 88804e3394f5f40dd6fed53f52b34503275a119c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 19 Jul 2023 17:16:27 +0330 Subject: [PATCH 594/775] Prepare for stress concentration considerations --- render/finiteelements/mesh/inp.go | 6 +++--- render/finiteelements/mesh/restraint_load.go | 20 +++++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index a5b7296a9..a77d2730a 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -89,7 +89,7 @@ func NewInp( // Figure out node and voxel for each load. // TODO: move this statement to the logic that writes loads to file. for _, l := range inp.Loads { - l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) + l.nodeID, l.voxel = inp.Mesh.Locate(l.Points) } return inp @@ -364,7 +364,7 @@ func (inp *Inp) writeBoundary() error { // Figure out node and voxel for each restraint. for _, r := range inp.Restraints { - r.nodeID, r.voxel = inp.Mesh.Locate(r.Location) + r.nodeID, r.voxel = inp.Mesh.Locate(r.Points) } // The closest node to any restraint is already computed. @@ -449,7 +449,7 @@ func (inp *Inp) writeLoad() error { // Figure out node and voxel for each. for _, l := range inp.Loads { - l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) + l.nodeID, l.voxel = inp.Mesh.Locate(l.Points) } // The closest node to any restraint is already computed. diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index 228eaabeb..b2e34c19b 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -5,9 +5,19 @@ import ( "github.com/deadsy/sdfx/vec/v3i" ) -// Single point constraint: one or more degrees of freedom are fixed for a given node. +// 1. Define each restraint by two things: +// 1.1. A collection of points, *not* by a single point. +// 1.2. Degrees of freedom that are fixed/free for all the points of the collection. +// 2. Assume those points are connected by straight lines. +// 3. Any voxel that intersects with those straight lines is considered rigid. +// 4. Create `*RIGID BODY` by all the elements or nodes inside those voxels. +// 5. Degree of freedom would be fixed/free for the `REF NODE` of the `*RIGID BODY` +// +// According to CCX manual, under the hood, a `*RIGID BODY` is actually a nonlinear multiple-point constraint (MPC). +// +// The objective: the stress concentration at the restraint may be alleviated by distributing it. type Restraint struct { - Location v3.Vec // Exact coordinate. + Points v3.Vec // Exact coordinates inside rigid body. IsFixedX bool // Is X degree of freedom fixed? IsFixedY bool // Is Y degree of freedom fixed? IsFixedZ bool // Is Z degree of freedom fixed? @@ -17,7 +27,7 @@ type Restraint struct { // Point loads are applied to the nodes of the mesh. type Load struct { - Location v3.Vec // Exact coordinate. + Points v3.Vec // Exact coordinates inside rigid body. Magnitude v3.Vec // X, Y, Z magnitude. voxel v3i.Vec // Containing voxel: to be computed by logic. nodeID uint32 // Eventual node to which the load is applied. To be computed. @@ -25,7 +35,7 @@ type Load struct { func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { return &Restraint{ - Location: location, + Points: location, IsFixedX: isFixedX, IsFixedY: isFixedY, IsFixedZ: isFixedZ, @@ -36,7 +46,7 @@ func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint func NewLoad(location, magnitude v3.Vec) *Load { return &Load{ - Location: location, + Points: location, Magnitude: magnitude, voxel: v3i.Vec{}, nodeID: 0, From fb6334df0683cb7f3e27ca3af8a270b70cd31560 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 09:33:01 +0330 Subject: [PATCH 595/775] Rename field --- render/finiteelements/mesh/inp.go | 6 +++--- render/finiteelements/mesh/restraint_load.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index a77d2730a..a5b7296a9 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -89,7 +89,7 @@ func NewInp( // Figure out node and voxel for each load. // TODO: move this statement to the logic that writes loads to file. for _, l := range inp.Loads { - l.nodeID, l.voxel = inp.Mesh.Locate(l.Points) + l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) } return inp @@ -364,7 +364,7 @@ func (inp *Inp) writeBoundary() error { // Figure out node and voxel for each restraint. for _, r := range inp.Restraints { - r.nodeID, r.voxel = inp.Mesh.Locate(r.Points) + r.nodeID, r.voxel = inp.Mesh.Locate(r.Location) } // The closest node to any restraint is already computed. @@ -449,7 +449,7 @@ func (inp *Inp) writeLoad() error { // Figure out node and voxel for each. for _, l := range inp.Loads { - l.nodeID, l.voxel = inp.Mesh.Locate(l.Points) + l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) } // The closest node to any restraint is already computed. diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index b2e34c19b..4016faccf 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -17,7 +17,7 @@ import ( // // The objective: the stress concentration at the restraint may be alleviated by distributing it. type Restraint struct { - Points v3.Vec // Exact coordinates inside rigid body. + Location v3.Vec // Exact coordinates inside rigid body. IsFixedX bool // Is X degree of freedom fixed? IsFixedY bool // Is Y degree of freedom fixed? IsFixedZ bool // Is Z degree of freedom fixed? @@ -27,7 +27,7 @@ type Restraint struct { // Point loads are applied to the nodes of the mesh. type Load struct { - Points v3.Vec // Exact coordinates inside rigid body. + Location v3.Vec // Exact coordinates inside rigid body. Magnitude v3.Vec // X, Y, Z magnitude. voxel v3i.Vec // Containing voxel: to be computed by logic. nodeID uint32 // Eventual node to which the load is applied. To be computed. @@ -35,7 +35,7 @@ type Load struct { func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { return &Restraint{ - Points: location, + Location: location, IsFixedX: isFixedX, IsFixedY: isFixedY, IsFixedZ: isFixedZ, @@ -46,7 +46,7 @@ func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint func NewLoad(location, magnitude v3.Vec) *Load { return &Load{ - Points: location, + Location: location, Magnitude: magnitude, voxel: v3i.Vec{}, nodeID: 0, From 9d9445133ae975a3db0b174ce529824714fe109d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 10:20:23 +0330 Subject: [PATCH 596/775] Get a collection of points for each restraint --- examples/finite_elements/main.go | 88 +++++++++++--------- render/finiteelements/mesh/restraint_load.go | 24 +++--- 2 files changed, 59 insertions(+), 53 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 99f555046..65525a86c 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -240,64 +240,70 @@ func dilationErosion(s sdf.SDF3) sdf.SDF3 { } func benchmarkSquareRestraint() []*mesh.Restraint { - // Four corners. - restraints := []*mesh.Restraint{ - mesh.NewRestraint(v3.Vec{X: 0, Y: 0, Z: 0}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: 17.32, Z: 0}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 17.32, Z: 0}, false, true, true), - } + restraints := []*mesh.Restraint{} - // Let's avoid stress concentration by increasing the number of restraints. - // Let's increase it so that most of the edge length is restrained. Not just corners. + locationPinned := []v3.Vec{} gap := 1.0 var y float64 for y <= 17.32 { - restraints = append(restraints, mesh.NewRestraint(v3.Vec{X: 0, Y: y, Z: 0}, true, true, true)) + locationPinned = append(locationPinned, v3.Vec{X: 0, Y: y, Z: 0}) y += gap } + restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) + + locationRoller := []v3.Vec{} y = 0 for y <= 17.32 { - restraints = append(restraints, mesh.NewRestraint(v3.Vec{X: 200, Y: y, Z: 0}, false, true, true)) + locationRoller = append(locationRoller, v3.Vec{X: 200, Y: y, Z: 0}) y += gap } + restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) + return restraints } func benchmarkCircleRestraint() []*mesh.Restraint { - restraints := []*mesh.Restraint{ - // The pinned end of 3D beam. - mesh.NewRestraint(v3.Vec{X: 0, Y: 0, Z: 0}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: -2.0313, Z: 0.213498}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: -3.97382, Z: 0.844661}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: -5.74266, Z: 1.8659}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: -7.26052, Z: 3.23259}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: -8.46107, Z: 4.885}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: -9.29182, Z: 6.7509}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: 2.0313, Z: 0.213498}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: 3.97382, Z: 0.844661}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: 5.74266, Z: 1.8659}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: 7.26052, Z: 3.23259}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: 8.46107, Z: 4.885}, true, true, true), - mesh.NewRestraint(v3.Vec{X: 0, Y: 9.29182, Z: 6.7509}, true, true, true), - - // The roller end of 3D beam. - mesh.NewRestraint(v3.Vec{X: 200, Y: 0, Z: 0}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: -2.0313, Z: 0.213498}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: -3.97382, Z: 0.844661}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: -5.74266, Z: 1.8659}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: -7.26052, Z: 3.23259}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: -8.46107, Z: 4.885}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: -9.29182, Z: 6.7509}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 2.0313, Z: 0.213498}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 3.97382, Z: 0.844661}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 5.74266, Z: 1.8659}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 7.26052, Z: 3.23259}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 8.46107, Z: 4.885}, false, true, true), - mesh.NewRestraint(v3.Vec{X: 200, Y: 9.29182, Z: 6.7509}, false, true, true), + restraints := make([]*mesh.Restraint, 0) + + // The pinned end of 3D beam. + locationPinned := []v3.Vec{ + v3.Vec{X: 0, Y: 0, Z: 0}, + v3.Vec{X: 0, Y: -2.0313, Z: 0.213498}, + v3.Vec{X: 0, Y: -3.97382, Z: 0.844661}, + v3.Vec{X: 0, Y: -5.74266, Z: 1.8659}, + v3.Vec{X: 0, Y: -7.26052, Z: 3.23259}, + v3.Vec{X: 0, Y: -8.46107, Z: 4.885}, + v3.Vec{X: 0, Y: -9.29182, Z: 6.7509}, + v3.Vec{X: 0, Y: 2.0313, Z: 0.213498}, + v3.Vec{X: 0, Y: 3.97382, Z: 0.844661}, + v3.Vec{X: 0, Y: 5.74266, Z: 1.8659}, + v3.Vec{X: 0, Y: 7.26052, Z: 3.23259}, + v3.Vec{X: 0, Y: 8.46107, Z: 4.885}, + v3.Vec{X: 0, Y: 9.29182, Z: 6.7509}, } + restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) + + // The roller end of 3D beam. + locationRoller := []v3.Vec{ + v3.Vec{X: 200, Y: 0, Z: 0}, + v3.Vec{X: 200, Y: -2.0313, Z: 0.213498}, + v3.Vec{X: 200, Y: -3.97382, Z: 0.844661}, + v3.Vec{X: 200, Y: -5.74266, Z: 1.8659}, + v3.Vec{X: 200, Y: -7.26052, Z: 3.23259}, + v3.Vec{X: 200, Y: -8.46107, Z: 4.885}, + v3.Vec{X: 200, Y: -9.29182, Z: 6.7509}, + v3.Vec{X: 200, Y: 2.0313, Z: 0.213498}, + v3.Vec{X: 200, Y: 3.97382, Z: 0.844661}, + v3.Vec{X: 200, Y: 5.74266, Z: 1.8659}, + v3.Vec{X: 200, Y: 7.26052, Z: 3.23259}, + v3.Vec{X: 200, Y: 8.46107, Z: 4.885}, + v3.Vec{X: 200, Y: 9.29182, Z: 6.7509}, + } + + restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) + return restraints } diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index 4016faccf..a19999729 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -17,23 +17,23 @@ import ( // // The objective: the stress concentration at the restraint may be alleviated by distributing it. type Restraint struct { - Location v3.Vec // Exact coordinates inside rigid body. - IsFixedX bool // Is X degree of freedom fixed? - IsFixedY bool // Is Y degree of freedom fixed? - IsFixedZ bool // Is Z degree of freedom fixed? - voxel v3i.Vec // Containing voxel: to be computed by logic. - nodeID uint32 // Eventual node to which the restraint is applied. To be computed. + Location []v3.Vec // Exact coordinates inside rigid body. + IsFixedX bool // Is X degree of freedom fixed? + IsFixedY bool // Is Y degree of freedom fixed? + IsFixedZ bool // Is Z degree of freedom fixed? + voxel v3i.Vec // Containing voxel: to be computed by logic. + nodeID uint32 // Eventual node to which the restraint is applied. To be computed. } // Point loads are applied to the nodes of the mesh. type Load struct { - Location v3.Vec // Exact coordinates inside rigid body. - Magnitude v3.Vec // X, Y, Z magnitude. - voxel v3i.Vec // Containing voxel: to be computed by logic. - nodeID uint32 // Eventual node to which the load is applied. To be computed. + Location []v3.Vec // Exact coordinates inside rigid body. + Magnitude v3.Vec // X, Y, Z magnitude. + voxel v3i.Vec // Containing voxel: to be computed by logic. + nodeID uint32 // Eventual node to which the load is applied. To be computed. } -func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { +func NewRestraint(location []v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { return &Restraint{ Location: location, IsFixedX: isFixedX, @@ -44,7 +44,7 @@ func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint } } -func NewLoad(location, magnitude v3.Vec) *Load { +func NewLoad(location []v3.Vec, magnitude v3.Vec) *Load { return &Load{ Location: location, Magnitude: magnitude, From 38190dd96394d6febe7187a8a059e6a8cb02fb7e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 10:22:41 +0330 Subject: [PATCH 597/775] Collection of points for each load --- examples/finite_elements/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 65525a86c..bb5f0e10b 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -53,8 +53,9 @@ func main() { var restraints []*mesh.Restraint // Gravity load is used for benchmarks. So, there is no point load. + location := []v3.Vec{v3.Vec{X: 0, Y: 0, Z: 0}} loads := []*mesh.Load{ - mesh.NewLoad(v3.Vec{X: 0, Y: 0, Z: 0}, v3.Vec{X: 0, Y: 0, Z: 0}), + mesh.NewLoad(location, v3.Vec{X: 0, Y: 0, Z: 0}), } switch benchmark { From de016917bdc1e610d34b8cbbf24ae3e0d1265beb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 10:58:00 +0330 Subject: [PATCH 598/775] Func: intersecting voxels with points b-box --- render/finiteelements/buffer/voxel.go | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 8f1de8e36..6d01add64 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -97,6 +97,40 @@ func (vg *VoxelGrid) Append(x, y, z int, value *Element) { vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data = append(vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data, value) } +// Compute the bounding box of all the input points. +// Return all the voxels that are intersecting with that bounding box. +func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) []v3i.Vec { + if len(points) == 0 { + return nil + } + + // compute the bounding box of all the input points + min, max := points[0], points[0] + for _, point := range points { + min = min.Min(point) + max = max.Max(point) + } + + var intersectingVoxels []v3i.Vec + + // iterate over all the voxels + for i, voxel := range vg.Voxels { + // check if the voxel intersects with the bounding box + if voxel.Max.Min(max) != max || voxel.Min.Max(min) != min { + continue + } + + // convert the 1D index to a 3D index + x := i / (vg.Len.Y * vg.Len.Z) + y := (i % (vg.Len.Y * vg.Len.Z)) / vg.Len.Z + z := i % vg.Len.Z + + intersectingVoxels = append(intersectingVoxels, v3i.Vec{X: x, Y: y, Z: z}) + } + + return intersectingVoxels +} + // To iterate over all voxels and get elements inside each voxel and do stuff with them. func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { for z := 0; z < vg.Len.Z; z++ { From c40b980ec58def067a78ead2390a1fbf61abd9aa Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 11:06:53 +0330 Subject: [PATCH 599/775] New func --- render/finiteelements/mesh/fem.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 288d981da..669aedbc4 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -123,6 +123,12 @@ func (m *Fem) Locate(location v3.Vec) (uint32, v3i.Vec) { return closestNode, v3i.Vec{X: idxX, Y: idxY, Z: idxZ} } +// Compute the bounding box of all the input points. +// Return all the voxels that are intersecting with that bounding box. +func (m *Fem) VoxelsIntersecting(points []v3.Vec) []v3i.Vec { + return m.IBuff.Grid.VoxelsIntersecting(points) +} + // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. func (m *Fem) WriteInp( path string, From eaa6a7ffdfe79aafeeea070e5792408733d0852b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 14:11:38 +0330 Subject: [PATCH 600/775] Finish up new restraint design --- render/finiteelements/buffer/voxel.go | 6 +- render/finiteelements/mesh/fem.go | 2 +- render/finiteelements/mesh/inp.go | 88 ++++++++++++++++---- render/finiteelements/mesh/restraint_load.go | 28 +++---- 4 files changed, 92 insertions(+), 32 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 6d01add64..c4a9de466 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -99,9 +99,9 @@ func (vg *VoxelGrid) Append(x, y, z int, value *Element) { // Compute the bounding box of all the input points. // Return all the voxels that are intersecting with that bounding box. -func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) []v3i.Vec { +func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { if len(points) == 0 { - return nil + return nil, v3.Vec{}, v3.Vec{} } // compute the bounding box of all the input points @@ -128,7 +128,7 @@ func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) []v3i.Vec { intersectingVoxels = append(intersectingVoxels, v3i.Vec{X: x, Y: y, Z: z}) } - return intersectingVoxels + return intersectingVoxels, min, max } // To iterate over all voxels and get elements inside each voxel and do stuff with them. diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 669aedbc4..a9610f851 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -125,7 +125,7 @@ func (m *Fem) Locate(location v3.Vec) (uint32, v3i.Vec) { // Compute the bounding box of all the input points. // Return all the voxels that are intersecting with that bounding box. -func (m *Fem) VoxelsIntersecting(points []v3.Vec) []v3i.Vec { +func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { return m.IBuff.Grid.VoxelsIntersecting(points) } diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index a5b7296a9..4e6ad2b3a 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -86,10 +86,12 @@ func NewInp( GravityMagnitude: gravityMagnitude, } + // TODO: complete loading. + // // Figure out node and voxel for each load. // TODO: move this statement to the logic that writes loads to file. for _, l := range inp.Loads { - l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) + l.voxels, _, _ = inp.Mesh.VoxelsIntersecting(l.Location) } return inp @@ -357,28 +359,84 @@ func (inp *Inp) writeBoundary() error { } defer f.Close() - _, err = f.WriteString("*BOUNDARY\n") - if err != nil { - return err - } - - // Figure out node and voxel for each restraint. + // Figure out reference node and voxels for each restraint. for _, r := range inp.Restraints { - r.nodeID, r.voxel = inp.Mesh.Locate(r.Location) + var min, max v3.Vec + r.voxels, min, max = inp.Mesh.VoxelsIntersecting(r.Location) + // Reference node is closest node to the b-box center. + // TODO: Does center make sense? + center := min.Add(max).DivScalar(2.0) + r.nodeREF, _ = inp.Mesh.Locate(center) } - // The closest node to any restraint is already computed. - for _, r := range inp.Restraints { + for i, r := range inp.Restraints { isFixedX, isFixedY, isFixedZ := r.IsFixedX, r.IsFixedY, r.IsFixedZ if !isFixedX && !isFixedY && !isFixedZ { - continue + panic("restraint has no fixed degree of freedom") + } + + nodeSet := make([]uint32, 0) + + for _, vox := range r.voxels { + + // Get elements in the voxel + elements := inp.Mesh.IBuff.Grid.Get(vox.X, vox.Y, vox.Z) + + for _, element := range elements { + for _, node := range element.Nodes { + // Node ID should be consistant with the temp vertex buffer. + // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. + vertex := inp.Mesh.vertex(node) + id := inp.TempVBuff.Id(vertex) + nodeSet = append(nodeSet, id) + } + } + } + + // Write node set for this restraint. + _, err = f.WriteString(fmt.Sprintf("*NSET,NSET=restraint%d\n", i+1)) + if err != nil { + return err + } + + for j, id := range nodeSet { + if j == len(nodeSet)-1 { + // The last one is written differently. + _, err = f.WriteString(fmt.Sprintf("%d\n", id+1)) + if err != nil { + return err + } + } else if j%15 == 0 { + // According to CCX manual: maximum 16 entries per line. + _, err = f.WriteString(fmt.Sprintf("%d,\n", id+1)) + if err != nil { + return err + } + } else { + _, err = f.WriteString(fmt.Sprintf("%d,", id+1)) + if err != nil { + return err + } + } } // Node ID should be consistant with the temp vertex buffer. // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. - vertex := inp.Mesh.vertex(r.nodeID) + vertex := inp.Mesh.vertex(r.nodeREF) id := inp.TempVBuff.Id(vertex) + // Define a rigid body consisting of the nodes belonging to node set. + _, err = f.WriteString(fmt.Sprintf("*RIGID BODY,NSET=restraint%d,REF NODE=%d\n", i+1, id+1)) + if err != nil { + return err + } + + // Put the boundary constraints on the reference node. + _, err = f.WriteString("*BOUNDARY\n") + if err != nil { + return err + } + // To be written: // // 1) Node ID. @@ -447,16 +505,18 @@ func (inp *Inp) writeLoad() error { return err } + // TODO: complete loading. + // Figure out node and voxel for each. for _, l := range inp.Loads { - l.nodeID, l.voxel = inp.Mesh.Locate(l.Location) + l.voxels, _, _ = inp.Mesh.VoxelsIntersecting(l.Location) } // The closest node to any restraint is already computed. for _, l := range inp.Loads { // Node ID should be consistant with the temp vertex buffer. // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. - vertex := inp.Mesh.vertex(l.nodeID) + vertex := inp.Mesh.vertex(l.nodeREF) id := inp.TempVBuff.Id(vertex) // To be written: diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index a19999729..4971ed9b2 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -17,20 +17,20 @@ import ( // // The objective: the stress concentration at the restraint may be alleviated by distributing it. type Restraint struct { - Location []v3.Vec // Exact coordinates inside rigid body. - IsFixedX bool // Is X degree of freedom fixed? - IsFixedY bool // Is Y degree of freedom fixed? - IsFixedZ bool // Is Z degree of freedom fixed? - voxel v3i.Vec // Containing voxel: to be computed by logic. - nodeID uint32 // Eventual node to which the restraint is applied. To be computed. + Location []v3.Vec // Exact coordinates inside rigid body. + IsFixedX bool // Is X degree of freedom fixed? + IsFixedY bool // Is Y degree of freedom fixed? + IsFixedZ bool // Is Z degree of freedom fixed? + voxels []v3i.Vec // Intersecting voxels: to be computed by logic. + nodeREF uint32 // Eventual node to which the restraint is applied. To be computed. } // Point loads are applied to the nodes of the mesh. type Load struct { - Location []v3.Vec // Exact coordinates inside rigid body. - Magnitude v3.Vec // X, Y, Z magnitude. - voxel v3i.Vec // Containing voxel: to be computed by logic. - nodeID uint32 // Eventual node to which the load is applied. To be computed. + Location []v3.Vec // Exact coordinates inside rigid body. + Magnitude v3.Vec // X, Y, Z magnitude. + voxels []v3i.Vec // Intersecting voxels: to be computed by logic. + nodeREF uint32 // Eventual node to which the load is applied. To be computed. } func NewRestraint(location []v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { @@ -39,8 +39,8 @@ func NewRestraint(location []v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restrai IsFixedX: isFixedX, IsFixedY: isFixedY, IsFixedZ: isFixedZ, - voxel: v3i.Vec{}, - nodeID: 0, + voxels: make([]v3i.Vec, 0), + nodeREF: 0, } } @@ -48,7 +48,7 @@ func NewLoad(location []v3.Vec, magnitude v3.Vec) *Load { return &Load{ Location: location, Magnitude: magnitude, - voxel: v3i.Vec{}, - nodeID: 0, + voxels: make([]v3i.Vec, 0), + nodeREF: 0, } } From ba79e083e6f82f8fd136e068694d9e08ebc25097 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 14:26:13 +0330 Subject: [PATCH 601/775] Remove extra labels --- examples/finite_elements/main.go | 54 ++++++++++++++++---------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index bb5f0e10b..08cef0fe7 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -53,7 +53,7 @@ func main() { var restraints []*mesh.Restraint // Gravity load is used for benchmarks. So, there is no point load. - location := []v3.Vec{v3.Vec{X: 0, Y: 0, Z: 0}} + location := []v3.Vec{{X: 0, Y: 0, Z: 0}} loads := []*mesh.Load{ mesh.NewLoad(location, v3.Vec{X: 0, Y: 0, Z: 0}), } @@ -270,38 +270,38 @@ func benchmarkCircleRestraint() []*mesh.Restraint { // The pinned end of 3D beam. locationPinned := []v3.Vec{ - v3.Vec{X: 0, Y: 0, Z: 0}, - v3.Vec{X: 0, Y: -2.0313, Z: 0.213498}, - v3.Vec{X: 0, Y: -3.97382, Z: 0.844661}, - v3.Vec{X: 0, Y: -5.74266, Z: 1.8659}, - v3.Vec{X: 0, Y: -7.26052, Z: 3.23259}, - v3.Vec{X: 0, Y: -8.46107, Z: 4.885}, - v3.Vec{X: 0, Y: -9.29182, Z: 6.7509}, - v3.Vec{X: 0, Y: 2.0313, Z: 0.213498}, - v3.Vec{X: 0, Y: 3.97382, Z: 0.844661}, - v3.Vec{X: 0, Y: 5.74266, Z: 1.8659}, - v3.Vec{X: 0, Y: 7.26052, Z: 3.23259}, - v3.Vec{X: 0, Y: 8.46107, Z: 4.885}, - v3.Vec{X: 0, Y: 9.29182, Z: 6.7509}, + {X: 0, Y: 0, Z: 0}, + {X: 0, Y: -2.0313, Z: 0.213498}, + {X: 0, Y: -3.97382, Z: 0.844661}, + {X: 0, Y: -5.74266, Z: 1.8659}, + {X: 0, Y: -7.26052, Z: 3.23259}, + {X: 0, Y: -8.46107, Z: 4.885}, + {X: 0, Y: -9.29182, Z: 6.7509}, + {X: 0, Y: 2.0313, Z: 0.213498}, + {X: 0, Y: 3.97382, Z: 0.844661}, + {X: 0, Y: 5.74266, Z: 1.8659}, + {X: 0, Y: 7.26052, Z: 3.23259}, + {X: 0, Y: 8.46107, Z: 4.885}, + {X: 0, Y: 9.29182, Z: 6.7509}, } restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) // The roller end of 3D beam. locationRoller := []v3.Vec{ - v3.Vec{X: 200, Y: 0, Z: 0}, - v3.Vec{X: 200, Y: -2.0313, Z: 0.213498}, - v3.Vec{X: 200, Y: -3.97382, Z: 0.844661}, - v3.Vec{X: 200, Y: -5.74266, Z: 1.8659}, - v3.Vec{X: 200, Y: -7.26052, Z: 3.23259}, - v3.Vec{X: 200, Y: -8.46107, Z: 4.885}, - v3.Vec{X: 200, Y: -9.29182, Z: 6.7509}, - v3.Vec{X: 200, Y: 2.0313, Z: 0.213498}, - v3.Vec{X: 200, Y: 3.97382, Z: 0.844661}, - v3.Vec{X: 200, Y: 5.74266, Z: 1.8659}, - v3.Vec{X: 200, Y: 7.26052, Z: 3.23259}, - v3.Vec{X: 200, Y: 8.46107, Z: 4.885}, - v3.Vec{X: 200, Y: 9.29182, Z: 6.7509}, + {X: 200, Y: 0, Z: 0}, + {X: 200, Y: -2.0313, Z: 0.213498}, + {X: 200, Y: -3.97382, Z: 0.844661}, + {X: 200, Y: -5.74266, Z: 1.8659}, + {X: 200, Y: -7.26052, Z: 3.23259}, + {X: 200, Y: -8.46107, Z: 4.885}, + {X: 200, Y: -9.29182, Z: 6.7509}, + {X: 200, Y: 2.0313, Z: 0.213498}, + {X: 200, Y: 3.97382, Z: 0.844661}, + {X: 200, Y: 5.74266, Z: 1.8659}, + {X: 200, Y: 7.26052, Z: 3.23259}, + {X: 200, Y: 8.46107, Z: 4.885}, + {X: 200, Y: 9.29182, Z: 6.7509}, } restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) From 6dd9296374ee1837b899d08884310877da047007 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 15:12:50 +0330 Subject: [PATCH 602/775] Fix bug: voxel intersection check --- render/finiteelements/buffer/voxel.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index c4a9de466..a6f160d4d 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -116,7 +116,7 @@ func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3. // iterate over all the voxels for i, voxel := range vg.Voxels { // check if the voxel intersects with the bounding box - if voxel.Max.Min(max) != max || voxel.Min.Max(min) != min { + if !DoesIntersect(voxel.Min, voxel.Max, min, max) { continue } @@ -131,6 +131,17 @@ func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3. return intersectingVoxels, min, max } +// Does two voxels or b-boxes intersect with each other? +func DoesIntersect(aMin, aMax, bMin, bMax v3.Vec) bool { + if aMin.X > bMax.X || aMin.Y > bMax.Y || aMin.Z > bMax.Z { + return false + } + if bMin.X > aMax.X || bMin.Y > aMax.Y || bMin.Z > aMax.Z { + return false + } + return true +} + // To iterate over all voxels and get elements inside each voxel and do stuff with them. func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { for z := 0; z < vg.Len.Z; z++ { From ec4e0fc9d5b354d64815f222a0aaeac4fd44d014 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 15:25:24 +0330 Subject: [PATCH 603/775] Fix: only 16 node IDs per line --- render/finiteelements/mesh/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 4e6ad2b3a..6597b6137 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -406,7 +406,7 @@ func (inp *Inp) writeBoundary() error { if err != nil { return err } - } else if j%15 == 0 { + } else if j != 0 && j%15 == 0 { // According to CCX manual: maximum 16 entries per line. _, err = f.WriteString(fmt.Sprintf("%d,\n", id+1)) if err != nil { From 62cd845fd322beb31890c17a922014d9516123d0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 16:48:55 +0330 Subject: [PATCH 604/775] Return error --- render/finiteelements/mesh/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 6597b6137..45860aeab 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -372,7 +372,7 @@ func (inp *Inp) writeBoundary() error { for i, r := range inp.Restraints { isFixedX, isFixedY, isFixedZ := r.IsFixedX, r.IsFixedY, r.IsFixedZ if !isFixedX && !isFixedY && !isFixedZ { - panic("restraint has no fixed degree of freedom") + return fmt.Errorf("restraint has no fixed degree of freedom") } nodeSet := make([]uint32, 0) From e88afc7356ff5a3493086580178f06471ddcf566 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 16:56:46 +0330 Subject: [PATCH 605/775] Change the way reference node is picked --- render/finiteelements/mesh/inp.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 45860aeab..04ae5e6f8 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -361,12 +361,11 @@ func (inp *Inp) writeBoundary() error { // Figure out reference node and voxels for each restraint. for _, r := range inp.Restraints { - var min, max v3.Vec - r.voxels, min, max = inp.Mesh.VoxelsIntersecting(r.Location) - // Reference node is closest node to the b-box center. - // TODO: Does center make sense? - center := min.Add(max).DivScalar(2.0) - r.nodeREF, _ = inp.Mesh.Locate(center) + r.voxels, _, _ = inp.Mesh.VoxelsIntersecting(r.Location) + // Reference node is picked as: + // 1st node of 1st element of 1st voxel. + // TODO: Does it make sense? Replace with a more sane approach. + r.nodeREF = inp.Mesh.IBuff.Grid.Get(r.voxels[0].X, r.voxels[0].Y, r.voxels[0].Z)[0].Nodes[0] } for i, r := range inp.Restraints { From 8bd7099b8010bd27cc85c5e44ab1b4f2178d715d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 20 Jul 2023 17:08:12 +0330 Subject: [PATCH 606/775] Avoid panic --- render/finiteelements/mesh/inp.go | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 04ae5e6f8..d0695f63e 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -7,6 +7,7 @@ import ( "github.com/deadsy/sdfx/render/finiteelements/buffer" v3 "github.com/deadsy/sdfx/vec/v3" + "github.com/deadsy/sdfx/vec/v3i" ) // Inp writes different types of finite elements as ABAQUS or CalculiX `inp` file. @@ -362,10 +363,26 @@ func (inp *Inp) writeBoundary() error { // Figure out reference node and voxels for each restraint. for _, r := range inp.Restraints { r.voxels, _, _ = inp.Mesh.VoxelsIntersecting(r.Location) - // Reference node is picked as: - // 1st node of 1st element of 1st voxel. + + pickFirstValidNode := func(voxels []v3i.Vec) (uint32, error) { + for _, vox := range r.voxels { + // Get elements in the voxel + elements := inp.Mesh.IBuff.Grid.Get(vox.X, vox.Y, vox.Z) + for _, element := range elements { + for _, node := range element.Nodes { + return node, nil + } + } + } + return 0, fmt.Errorf("there is no valid nodes in voxels of a boundary condition") + } + + // Reference node is picked here. // TODO: Does it make sense? Replace with a more sane approach. - r.nodeREF = inp.Mesh.IBuff.Grid.Get(r.voxels[0].X, r.voxels[0].Y, r.voxels[0].Z)[0].Nodes[0] + r.nodeREF, err = pickFirstValidNode(r.voxels) + if err != nil { + return err + } } for i, r := range inp.Restraints { From e51dce78a5b54146391508e0a206869708948fe3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 11:05:12 +0330 Subject: [PATCH 607/775] Simplify index calculation from 1D to 3D --- render/finiteelements/buffer/voxel.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index a6f160d4d..6040879c5 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -121,9 +121,9 @@ func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3. } // convert the 1D index to a 3D index - x := i / (vg.Len.Y * vg.Len.Z) - y := (i % (vg.Len.Y * vg.Len.Z)) / vg.Len.Z z := i % vg.Len.Z + y := (i / vg.Len.Z) % vg.Len.Y + x := (i / vg.Len.Z) / vg.Len.Y intersectingVoxels = append(intersectingVoxels, v3i.Vec{X: x, Y: y, Z: z}) } From 0bfb394cc26b4337b660e9380a6ed815a33943de Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 13:14:48 +0330 Subject: [PATCH 608/775] Funcs to convert 3D to 1D indexing and vice versa --- render/finiteelements/buffer/voxel.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 6040879c5..65e9162bb 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -78,23 +78,38 @@ func NewVoxelGrid(len v3i.Vec, dim v3.Vec, mins, maxs []v3.Vec) *VoxelGrid { return vg } +// This func must be consistent with `(r *MarchingCubesFEUniform) Voxels` func. +// This func must be consistent with `marchingCubesFE` func too. +func (vg *VoxelGrid) index1Dto3D(i int) (int, int, int) { + z := i % vg.Len.Z + y := (i / vg.Len.Z) % vg.Len.Y + x := (i / vg.Len.Z) / vg.Len.Y + return x, y, z +} + +// This func must be consistent with `(r *MarchingCubesFEUniform) Voxels` func. +// This func must be consistent with `marchingCubesFE` func too. +func (vg *VoxelGrid) index3Dto1D(x, y, z int) int { + return x*vg.Len.Y*vg.Len.Z + y*vg.Len.Z + z +} + func (vg *VoxelGrid) Size() (int, int, int) { return vg.Len.X, vg.Len.Y, vg.Len.Z } // To get all the elements inside a voxel. func (vg *VoxelGrid) Get(x, y, z int) []*Element { - return vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data + return vg.Voxels[vg.index3Dto1D(x, y, z)].data } // To set all the elements inside a voxel at once. func (vg *VoxelGrid) Set(x, y, z int, value []*Element) { - vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data = value + vg.Voxels[vg.index3Dto1D(x, y, z)].data = value } // To append a single element to the elements inside a voxel. func (vg *VoxelGrid) Append(x, y, z int, value *Element) { - vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data = append(vg.Voxels[x*vg.Len.Y*vg.Len.Z+y*vg.Len.Z+z].data, value) + vg.Voxels[vg.index3Dto1D(x, y, z)].data = append(vg.Voxels[vg.index3Dto1D(x, y, z)].data, value) } // Compute the bounding box of all the input points. @@ -121,9 +136,7 @@ func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3. } // convert the 1D index to a 3D index - z := i % vg.Len.Z - y := (i / vg.Len.Z) % vg.Len.Y - x := (i / vg.Len.Z) / vg.Len.Y + x, y, z := vg.index1Dto3D(i) intersectingVoxels = append(intersectingVoxels, v3i.Vec{X: x, Y: y, Z: z}) } From f64b54199d2b06dce254b5cfe6d1b07d3746463a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 13:25:12 +0330 Subject: [PATCH 609/775] Try to fix 3D & 1D indexing conversion --- render/finiteelements/buffer/voxel.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 65e9162bb..553534708 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -81,16 +81,16 @@ func NewVoxelGrid(len v3i.Vec, dim v3.Vec, mins, maxs []v3.Vec) *VoxelGrid { // This func must be consistent with `(r *MarchingCubesFEUniform) Voxels` func. // This func must be consistent with `marchingCubesFE` func too. func (vg *VoxelGrid) index1Dto3D(i int) (int, int, int) { - z := i % vg.Len.Z - y := (i / vg.Len.Z) % vg.Len.Y - x := (i / vg.Len.Z) / vg.Len.Y + y := i % vg.Len.Y + x := (i / vg.Len.Y) % vg.Len.X + z := i / (vg.Len.Y * vg.Len.X) return x, y, z } // This func must be consistent with `(r *MarchingCubesFEUniform) Voxels` func. // This func must be consistent with `marchingCubesFE` func too. func (vg *VoxelGrid) index3Dto1D(x, y, z int) int { - return x*vg.Len.Y*vg.Len.Z + y*vg.Len.Z + z + return z*vg.Len.X*vg.Len.Y + x*vg.Len.Y + y } func (vg *VoxelGrid) Size() (int, int, int) { From 975c7e7914e5bce834947afcf39fca94cf90e840 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 13:49:18 +0330 Subject: [PATCH 610/775] Run example according to element config --- examples/finite_elements/main.go | 215 +++++++++++++++++-------------- 1 file changed, 120 insertions(+), 95 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 08cef0fe7..7ada0836f 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -23,7 +23,6 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -// Declare the enum using iota and const type Benchmark int const ( @@ -34,11 +33,23 @@ const ( Unknown ) +type ElementConfig int + +const ( + Tet4 ElementConfig = iota + 1 // tet4 i.e. 4-node tetrahedron + Tet10 // tet10 i.e. 10-node tetrahedron + Hex8 // hex8 i.e. 8-node hexahedron + Hex20 // hex20 i.e. 20-node hexahedron + Hex8Tet4 // hex8 and tet4 + Hex20Tet10 // hex20 and tet10 +) + // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { benchmark := Square + elementconfig := Hex20Tet10 // Optional argument from 1 to 4 to specify the benchmark to run. if len(os.Args) > 1 { @@ -49,6 +60,15 @@ func main() { benchmark = Benchmark(bmint) } + // Optional argument from 1 to 6 to specify the elements to generate. + if len(os.Args) > 2 { + ecint, err := strconv.Atoi(os.Args[2]) + if err != nil { + log.Fatalf("error: %s", err) + } + elementconfig = ElementConfig(ecint) + } + // To be set for each benchmark. var restraints []*mesh.Restraint @@ -61,14 +81,14 @@ func main() { switch benchmark { case Square: restraints = benchmarkSquareRestraint() - benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraints, loads) + benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraints, loads, elementconfig) case Circle: restraints = benchmarkCircleRestraint() - benchmarkRun("../../files/benchmark-circle.stl", 50, 0, 3, restraints, loads) + benchmarkRun("../../files/benchmark-circle.stl", 50, 0, 3, restraints, loads, elementconfig) case Pipe: - benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads) + benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads, elementconfig) case I: - benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads) + benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads, elementconfig) default: } } @@ -81,6 +101,7 @@ func benchmarkRun( layerStart, layerEnd int, restraints []*mesh.Restraint, loads []*mesh.Load, + elementconfig ElementConfig, ) { // read the stl file. file, err := os.OpenFile(stl, os.O_RDONLY, 0400) @@ -94,96 +115,100 @@ func benchmarkRun( log.Fatalf("error: %s", err) } - // tet4 i.e. 4-node tetrahedron - err = fe(inSdf, resolution, render.Linear, render.Tetrahedral, "tet4.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet4 i.e. 4-node tetrahedron - err = feLayers( - inSdf, resolution, render.Linear, render.Tetrahedral, - fmt.Sprintf("tet4--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet10 i.e. 10-node tetrahedron - err = fe(inSdf, resolution, render.Quadratic, render.Tetrahedral, "tet10.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - // tet10 i.e. 10-node tetrahedron - err = feLayers( - inSdf, resolution, render.Quadratic, render.Tetrahedral, - fmt.Sprintf("tet10--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 i.e. 8-node hexahedron - err = fe(inSdf, resolution, render.Linear, render.Hexahedral, "hex8.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 i.e. 8-node hexahedron - err = feLayers(inSdf, resolution, render.Linear, render.Hexahedral, - fmt.Sprintf("hex8--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 i.e. 20-node hexahedron - err = fe(inSdf, resolution, render.Quadratic, render.Hexahedral, "hex20.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 i.e. 20-node hexahedron - err = feLayers(inSdf, resolution, render.Quadratic, render.Hexahedral, - fmt.Sprintf("hex20--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 and tet4 - err = fe(inSdf, resolution, render.Linear, render.Both, "hex8tet4.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex8 and tet4 - err = feLayers(inSdf, resolution, render.Linear, render.Both, - fmt.Sprintf("hex8tet4--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 and tet10 - err = fe(inSdf, resolution, render.Quadratic, render.Both, "hex20tet10.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - // hex20 and tet10 - err = feLayers(inSdf, resolution, render.Quadratic, render.Both, - fmt.Sprintf("hex20tet10--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) + switch elementconfig { + case Tet4: + { + + err = fe(inSdf, resolution, render.Linear, render.Tetrahedral, "tet4.inp", restraints, loads) + if err != nil { + log.Fatalf("error: %s", err) + } + + err = feLayers( + inSdf, resolution, render.Linear, render.Tetrahedral, + fmt.Sprintf("tet4--layers-%v-to-%v.inp", layerStart, layerEnd), + restraints, loads, layerStart, layerEnd, + ) + if err != nil { + log.Fatalf("error: %s", err) + } + } + case Tet10: + { + err = fe(inSdf, resolution, render.Quadratic, render.Tetrahedral, "tet10.inp", restraints, loads) + if err != nil { + log.Fatalf("error: %s", err) + } + + err = feLayers( + inSdf, resolution, render.Quadratic, render.Tetrahedral, + fmt.Sprintf("tet10--layers-%v-to-%v.inp", layerStart, layerEnd), + restraints, loads, layerStart, layerEnd, + ) + if err != nil { + log.Fatalf("error: %s", err) + } + } + case Hex8: + { + err = fe(inSdf, resolution, render.Linear, render.Hexahedral, "hex8.inp", restraints, loads) + if err != nil { + log.Fatalf("error: %s", err) + } + + err = feLayers(inSdf, resolution, render.Linear, render.Hexahedral, + fmt.Sprintf("hex8--layers-%v-to-%v.inp", layerStart, layerEnd), + restraints, loads, layerStart, layerEnd, + ) + if err != nil { + log.Fatalf("error: %s", err) + } + } + case Hex20: + { + err = fe(inSdf, resolution, render.Quadratic, render.Hexahedral, "hex20.inp", restraints, loads) + if err != nil { + log.Fatalf("error: %s", err) + } + + err = feLayers(inSdf, resolution, render.Quadratic, render.Hexahedral, + fmt.Sprintf("hex20--layers-%v-to-%v.inp", layerStart, layerEnd), + restraints, loads, layerStart, layerEnd, + ) + if err != nil { + log.Fatalf("error: %s", err) + } + } + case Hex8Tet4: + { + err = fe(inSdf, resolution, render.Linear, render.Both, "hex8tet4.inp", restraints, loads) + if err != nil { + log.Fatalf("error: %s", err) + } + + err = feLayers(inSdf, resolution, render.Linear, render.Both, + fmt.Sprintf("hex8tet4--layers-%v-to-%v.inp", layerStart, layerEnd), + restraints, loads, layerStart, layerEnd, + ) + if err != nil { + log.Fatalf("error: %s", err) + } + } + case Hex20Tet10: + { + err = fe(inSdf, resolution, render.Quadratic, render.Both, "hex20tet10.inp", restraints, loads) + if err != nil { + log.Fatalf("error: %s", err) + } + + err = feLayers(inSdf, resolution, render.Quadratic, render.Both, + fmt.Sprintf("hex20tet10--layers-%v-to-%v.inp", layerStart, layerEnd), + restraints, loads, layerStart, layerEnd, + ) + if err != nil { + log.Fatalf("error: %s", err) + } + } } } From 1df056719807c555f49b9c27ea01a4a75f2086b5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 15:51:27 +0330 Subject: [PATCH 611/775] Write degrees of freedom for boundaries separately --- render/finiteelements/mesh/inp.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index d0695f63e..32d2cc60e 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -463,17 +463,33 @@ func (inp *Inp) writeBoundary() error { // Note: written node ID would start from one not zero. if isFixedX && isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1,3\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,2\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,3\n", id+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } } else if isFixedX && isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1,2\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,2\n", id+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } } else if !isFixedX && isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,2,3\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("%d,2\n", id+1)) + if err != nil { + panic("Couldn't write boundary to file: " + err.Error()) + } + _, err = f.WriteString(fmt.Sprintf("%d,3\n", id+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } From 9b5c24d5adddb6409eed4e10a9f542a326091e4b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 15:56:02 +0330 Subject: [PATCH 612/775] Remove TODO --- render/finiteelements/mesh/inp.go | 1 - 1 file changed, 1 deletion(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 32d2cc60e..3ac51fbfc 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -494,7 +494,6 @@ func (inp *Inp) writeBoundary() error { panic("Couldn't write boundary to file: " + err.Error()) } } else if isFixedX && !isFixedY && isFixedZ { - // TODO: Can we write this case by just one line, not two lines? _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) From 8a05737ad9d8b38fd459e717b3a159c96c8f8929 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 16:18:46 +0330 Subject: [PATCH 613/775] Remove `rigid body` --- render/finiteelements/mesh/inp.go | 58 +++++--------------- render/finiteelements/mesh/restraint_load.go | 2 - 2 files changed, 13 insertions(+), 47 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 3ac51fbfc..51f34cf24 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -7,7 +7,6 @@ import ( "github.com/deadsy/sdfx/render/finiteelements/buffer" v3 "github.com/deadsy/sdfx/vec/v3" - "github.com/deadsy/sdfx/vec/v3i" ) // Inp writes different types of finite elements as ABAQUS or CalculiX `inp` file. @@ -363,26 +362,6 @@ func (inp *Inp) writeBoundary() error { // Figure out reference node and voxels for each restraint. for _, r := range inp.Restraints { r.voxels, _, _ = inp.Mesh.VoxelsIntersecting(r.Location) - - pickFirstValidNode := func(voxels []v3i.Vec) (uint32, error) { - for _, vox := range r.voxels { - // Get elements in the voxel - elements := inp.Mesh.IBuff.Grid.Get(vox.X, vox.Y, vox.Z) - for _, element := range elements { - for _, node := range element.Nodes { - return node, nil - } - } - } - return 0, fmt.Errorf("there is no valid nodes in voxels of a boundary condition") - } - - // Reference node is picked here. - // TODO: Does it make sense? Replace with a more sane approach. - r.nodeREF, err = pickFirstValidNode(r.voxels) - if err != nil { - return err - } } for i, r := range inp.Restraints { @@ -436,17 +415,6 @@ func (inp *Inp) writeBoundary() error { } } - // Node ID should be consistant with the temp vertex buffer. - // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. - vertex := inp.Mesh.vertex(r.nodeREF) - id := inp.TempVBuff.Id(vertex) - - // Define a rigid body consisting of the nodes belonging to node set. - _, err = f.WriteString(fmt.Sprintf("*RIGID BODY,NSET=restraint%d,REF NODE=%d\n", i+1, id+1)) - if err != nil { - return err - } - // Put the boundary constraints on the reference node. _, err = f.WriteString("*BOUNDARY\n") if err != nil { @@ -455,7 +423,7 @@ func (inp *Inp) writeBoundary() error { // To be written: // - // 1) Node ID. + // 1) Node number/ID or node set label. // 2) First degree of freedom constrained. // 3) Last degree of freedom constrained. This field may be left blank if only // one degree of freedom is constrained. @@ -463,57 +431,57 @@ func (inp *Inp) writeBoundary() error { // Note: written node ID would start from one not zero. if isFixedX && isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,1\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } - _, err = f.WriteString(fmt.Sprintf("%d,2\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,2\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } - _, err = f.WriteString(fmt.Sprintf("%d,3\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,3\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } } else if isFixedX && isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,1\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } - _, err = f.WriteString(fmt.Sprintf("%d,2\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,2\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } } else if !isFixedX && isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,2\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,2\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } - _, err = f.WriteString(fmt.Sprintf("%d,3\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,3\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } } else if isFixedX && !isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,1\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } - _, err = f.WriteString(fmt.Sprintf("%d,3\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,3\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } } else if isFixedX && !isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,1\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,1\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } } else if !isFixedX && isFixedY && !isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,2\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,2\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } } else if !isFixedX && !isFixedY && isFixedZ { - _, err = f.WriteString(fmt.Sprintf("%d,3\n", id+1)) + _, err = f.WriteString(fmt.Sprintf("restraint%d,3\n", i+1)) if err != nil { panic("Couldn't write boundary to file: " + err.Error()) } diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index 4971ed9b2..dd9dd4bf9 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -22,7 +22,6 @@ type Restraint struct { IsFixedY bool // Is Y degree of freedom fixed? IsFixedZ bool // Is Z degree of freedom fixed? voxels []v3i.Vec // Intersecting voxels: to be computed by logic. - nodeREF uint32 // Eventual node to which the restraint is applied. To be computed. } // Point loads are applied to the nodes of the mesh. @@ -40,7 +39,6 @@ func NewRestraint(location []v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restrai IsFixedY: isFixedY, IsFixedZ: isFixedZ, voxels: make([]v3i.Vec, 0), - nodeREF: 0, } } From 911c5bd583ebb0f593dfa83b1bdc1bee18b94c1a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 16:21:32 +0330 Subject: [PATCH 614/775] Do not dilate SDF, keep it as is --- examples/finite_elements/main.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 7ada0836f..d307dd652 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -12,7 +12,6 @@ package main import ( "fmt" "log" - "math" "os" "strconv" @@ -217,8 +216,6 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth restraints []*mesh.Restraint, loads []*mesh.Load, ) error { - s = dilationErosion(s) - // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) @@ -234,8 +231,6 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape loads []*mesh.Load, layerStart, layerEnd int, ) error { - s = dilationErosion(s) - // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) @@ -243,28 +238,6 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) } -// By dilating SDF a little bit we may actually get rid of -// bad elements like disconnected or improperly connected elements. -// Erode so that SDF returns to its original size, well almost. -// -// TODO: run benchmarks without this to test. -func dilationErosion(s sdf.SDF3) sdf.SDF3 { - min := s.BoundingBox().Min - max := s.BoundingBox().Max - - dimX := (max.X - min.X) - dimY := (max.Y - min.Y) - dimZ := (max.Z - min.Z) - - // What percent is preferred? Calibration is done a bit. - factor := math.Min(dimX, math.Min(dimY, dimZ)) * float64(0.02) - - dilation := sdf.Offset3D(s, factor) - erosion := sdf.Offset3D(dilation, -factor) - - return erosion -} - func benchmarkSquareRestraint() []*mesh.Restraint { restraints := []*mesh.Restraint{} From fd25ba1866d3da2cddcd35717887b8e1cbe6d26c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 16:31:41 +0330 Subject: [PATCH 615/775] Each restraint has less points in it: To make displacements more realistic or larger. --- examples/finite_elements/main.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index d307dd652..57ff7b11e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -271,16 +271,8 @@ func benchmarkCircleRestraint() []*mesh.Restraint { {X: 0, Y: 0, Z: 0}, {X: 0, Y: -2.0313, Z: 0.213498}, {X: 0, Y: -3.97382, Z: 0.844661}, - {X: 0, Y: -5.74266, Z: 1.8659}, - {X: 0, Y: -7.26052, Z: 3.23259}, - {X: 0, Y: -8.46107, Z: 4.885}, - {X: 0, Y: -9.29182, Z: 6.7509}, {X: 0, Y: 2.0313, Z: 0.213498}, {X: 0, Y: 3.97382, Z: 0.844661}, - {X: 0, Y: 5.74266, Z: 1.8659}, - {X: 0, Y: 7.26052, Z: 3.23259}, - {X: 0, Y: 8.46107, Z: 4.885}, - {X: 0, Y: 9.29182, Z: 6.7509}, } restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) @@ -290,16 +282,8 @@ func benchmarkCircleRestraint() []*mesh.Restraint { {X: 200, Y: 0, Z: 0}, {X: 200, Y: -2.0313, Z: 0.213498}, {X: 200, Y: -3.97382, Z: 0.844661}, - {X: 200, Y: -5.74266, Z: 1.8659}, - {X: 200, Y: -7.26052, Z: 3.23259}, - {X: 200, Y: -8.46107, Z: 4.885}, - {X: 200, Y: -9.29182, Z: 6.7509}, {X: 200, Y: 2.0313, Z: 0.213498}, {X: 200, Y: 3.97382, Z: 0.844661}, - {X: 200, Y: 5.74266, Z: 1.8659}, - {X: 200, Y: 7.26052, Z: 3.23259}, - {X: 200, Y: 8.46107, Z: 4.885}, - {X: 200, Y: 9.29182, Z: 6.7509}, } restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) From b09e08a98e1ad45b99452a2d28f032e2ce2617d2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 16:36:07 +0330 Subject: [PATCH 616/775] Remove `rigid body` comment --- render/finiteelements/mesh/restraint_load.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index dd9dd4bf9..5a95656e9 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -8,12 +8,10 @@ import ( // 1. Define each restraint by two things: // 1.1. A collection of points, *not* by a single point. // 1.2. Degrees of freedom that are fixed/free for all the points of the collection. -// 2. Assume those points are connected by straight lines. -// 3. Any voxel that intersects with those straight lines is considered rigid. -// 4. Create `*RIGID BODY` by all the elements or nodes inside those voxels. -// 5. Degree of freedom would be fixed/free for the `REF NODE` of the `*RIGID BODY` -// -// According to CCX manual, under the hood, a `*RIGID BODY` is actually a nonlinear multiple-point constraint (MPC). +// 2. Assume a bounding box around all those points. +// 3. Any voxel that intersects with the bounding box is considered inside restraint. +// 4. Create `*BOUNDARY` for all the nodes inside those voxels. +// 5. Degree of freedom would be fixed/free for all those nodes. // // The objective: the stress concentration at the restraint may be alleviated by distributing it. type Restraint struct { From 18af312be8276600f26201359fab6d37ff1186ff Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 22 Jul 2023 16:38:48 +0330 Subject: [PATCH 617/775] Comment --- render/finiteelements/mesh/restraint_load.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/mesh/restraint_load.go b/render/finiteelements/mesh/restraint_load.go index 5a95656e9..a96c0fd60 100644 --- a/render/finiteelements/mesh/restraint_load.go +++ b/render/finiteelements/mesh/restraint_load.go @@ -15,7 +15,7 @@ import ( // // The objective: the stress concentration at the restraint may be alleviated by distributing it. type Restraint struct { - Location []v3.Vec // Exact coordinates inside rigid body. + Location []v3.Vec // Exact coordinates inside restraint. IsFixedX bool // Is X degree of freedom fixed? IsFixedY bool // Is Y degree of freedom fixed? IsFixedZ bool // Is Z degree of freedom fixed? @@ -24,7 +24,7 @@ type Restraint struct { // Point loads are applied to the nodes of the mesh. type Load struct { - Location []v3.Vec // Exact coordinates inside rigid body. + Location []v3.Vec // Exact coordinates inside restraint. Magnitude v3.Vec // X, Y, Z magnitude. voxels []v3i.Vec // Intersecting voxels: to be computed by logic. nodeREF uint32 // Eventual node to which the load is applied. To be computed. From 8958f1094886847d6ba9e694ea219aab48199a0d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 23 Jul 2023 15:31:15 +0330 Subject: [PATCH 618/775] Restraints for 3rd benchmark --- examples/finite_elements/main.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 57ff7b11e..654ee8340 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -85,6 +85,7 @@ func main() { restraints = benchmarkCircleRestraint() benchmarkRun("../../files/benchmark-circle.stl", 50, 0, 3, restraints, loads, elementconfig) case Pipe: + restraints = benchmarkPipeRestraint() benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads, elementconfig) case I: benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads, elementconfig) @@ -290,3 +291,31 @@ func benchmarkCircleRestraint() []*mesh.Restraint { return restraints } + +func benchmarkPipeRestraint() []*mesh.Restraint { + restraints := make([]*mesh.Restraint, 0) + + // The pinned end of 3D beam. + locationPinned := []v3.Vec{ + {X: 0, Y: 0, Z: 0}, + {X: 0, Y: -2.0313, Z: 0.213498}, + {X: 0, Y: -3.97382, Z: 0.844661}, + {X: 0, Y: 2.0313, Z: 0.213498}, + {X: 0, Y: 3.97382, Z: 0.844661}, + } + + restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) + + // The roller end of 3D beam. + locationRoller := []v3.Vec{ + {X: 200, Y: 0, Z: 0}, + {X: 200, Y: -2.0313, Z: 0.213498}, + {X: 200, Y: -3.97382, Z: 0.844661}, + {X: 200, Y: 2.0313, Z: 0.213498}, + {X: 200, Y: 3.97382, Z: 0.844661}, + } + + restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) + + return restraints +} From b8cbceedb8349af9ec725f8febbfda57a265ef4f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 23 Jul 2023 15:49:40 +0330 Subject: [PATCH 619/775] Restraint for I-shaped benchmark --- examples/finite_elements/main.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 654ee8340..5ad16c013 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -88,6 +88,7 @@ func main() { restraints = benchmarkPipeRestraint() benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads, elementconfig) case I: + restraints = benchmarkIRestraint() benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads, elementconfig) default: } @@ -319,3 +320,28 @@ func benchmarkPipeRestraint() []*mesh.Restraint { return restraints } + +func benchmarkIRestraint() []*mesh.Restraint { + restraints := []*mesh.Restraint{} + + locationPinned := []v3.Vec{} + gap := 1.0 + var y float64 + for y <= 25 { + locationPinned = append(locationPinned, v3.Vec{X: 0, Y: y, Z: 0}) + y += gap + } + + restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) + + locationRoller := []v3.Vec{} + y = 0 + for y <= 25 { + locationRoller = append(locationRoller, v3.Vec{X: 200, Y: y, Z: 0}) + y += gap + } + + restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) + + return restraints +} From af21c8dcc1720ad7a3c6122106f1678f332ff42d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 24 Jul 2023 16:31:52 +0330 Subject: [PATCH 620/775] Fix 3rd benchmark, pipe: just increment resolution --- examples/finite_elements/main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 5ad16c013..800ad0b39 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -86,7 +86,10 @@ func main() { benchmarkRun("../../files/benchmark-circle.stl", 50, 0, 3, restraints, loads, elementconfig) case Pipe: restraints = benchmarkPipeRestraint() - benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads, elementconfig) + // When resolution is `50`, the pipe benchmark misses some necessary finite elements. + // By incrementing it to `51`, the problem is fixed. + // TODO: Why does resolution have a high sensitivity? + benchmarkRun("../../files/benchmark-pipe.stl", 51, 0, 3, restraints, loads, elementconfig) case I: restraints = benchmarkIRestraint() benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads, elementconfig) From 2bb674011931777a838cf3f4b4f7a1c54643af22 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 24 Jul 2023 16:50:22 +0330 Subject: [PATCH 621/775] Allow running teapot in addition to benchmarks --- examples/finite_elements/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 800ad0b39..3426298f3 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -94,6 +94,8 @@ func main() { restraints = benchmarkIRestraint() benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads, elementconfig) default: + // If no valid benchmark is picked, run for the teapot. + benchmarkRun("../../files/teapot.stl", 50, 0, 15, restraints, loads, elementconfig) } } From dde47a6ae0009158f0695a25f27016dccf3833ac Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 24 Jul 2023 17:02:44 +0330 Subject: [PATCH 622/775] Increase teapot resolution: didn't solve artifact --- examples/finite_elements/main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 3426298f3..f5451cc8f 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -29,7 +29,6 @@ const ( Circle Pipe I - Unknown ) type ElementConfig int @@ -95,7 +94,7 @@ func main() { benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads, elementconfig) default: // If no valid benchmark is picked, run for the teapot. - benchmarkRun("../../files/teapot.stl", 50, 0, 15, restraints, loads, elementconfig) + benchmarkRun("../../files/teapot.stl", 61, 0, 18, restraints, loads, elementconfig) } } From df0f1d175eef353b2184fbeda56dc1119198ee5b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 25 Jul 2023 11:53:46 +0330 Subject: [PATCH 623/775] Test: always use point at edge middle --- render/marchfehelper.go | 14 ++++++++++++++ render/marchfelogic.go | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/render/marchfehelper.go b/render/marchfehelper.go index eecd8cf1f..34679b3cb 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -109,6 +109,20 @@ func point(edges [12]v3.Vec, corners [8]v3.Vec, index int) v3.Vec { } } +// ----------------------------------------------------------------------------- +// To avoid distorted tetrahedron with non-positive Jacobian or with flat shape or with degenerate faces. +// Regradless of input values at corners, return the point at the middle of the edge. +func mcInterpolateFE(p1, p2 v3.Vec, v1, v2, x float64) v3.Vec { + // Pick the half way point + t := 0.5 + + return v3.Vec{ + X: p1.X + t*(p2.X-p1.X), + Y: p1.Y + t*(p2.Y-p1.Y), + Z: p1.Z + t*(p2.Z-p1.Z), + } +} + //----------------------------------------------------------------------------- // Is a tetrahedron almost flat? diff --git a/render/marchfelogic.go b/render/marchfelogic.go index 805f7d20e..cd23fc600 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -297,7 +297,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) if mcEdgeTable[index]&bit != 0 { a := mcPairTable[i][0] b := mcPairTable[i][1] - points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) + points[i] = mcInterpolateFE(p[a], p[b], v[a], v[b], x) } } From db7fd4ddcac4660d0f98283680468abe921a271b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 25 Jul 2023 15:06:49 +0330 Subject: [PATCH 624/775] Undo a method: didn't work, artifact is observed Reverts commit: 78a82a08311d3ce2f45271b7fa07ac384e9cae0a --- render/marchfehelper.go | 84 ----------------------------------------- render/marchfelogic.go | 45 +++++++++++----------- 2 files changed, 22 insertions(+), 107 deletions(-) diff --git a/render/marchfehelper.go b/render/marchfehelper.go index 34679b3cb..127bd4fce 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -2,96 +2,12 @@ package render import ( "math" - "sync" - "github.com/deadsy/sdfx/sdf" v3 "github.com/deadsy/sdfx/vec/v3" - "github.com/deadsy/sdfx/vec/v3i" ) //----------------------------------------------------------------------------- -// 3D print slicing is done along Z direction. -// Therefore, our slices are in XY plane. -type layerXY struct { - base v3.Vec // base coordinate of layer - inc v3.Vec // dx, dy, dz for each step - steps v3i.Vec // number of x,y,z steps - val0 []float64 // SDF values for z layer - val1 []float64 // SDF values for z + dz layer -} - -func newLayerXY(base, inc v3.Vec, steps v3i.Vec) *layerXY { - return &layerXY{base, inc, steps, nil, nil} -} - -// Evaluate the SDF for a given XY layer -func (l *layerXY) Evaluate(s sdf.SDF3, z int) { - - // Swap the layers - l.val0, l.val1 = l.val1, l.val0 - - nx, ny := l.steps.X, l.steps.Y - dx, dy, dz := l.inc.X, l.inc.Y, l.inc.Z - - // allocate storage - if l.val1 == nil { - l.val1 = make([]float64, (nx+1)*(ny+1)) - } - - // setup the loop variables - var p v3.Vec - p.Z = l.base.Z + float64(z)*dz - - // define the base struct for requesting evaluation - eReq := evalReq{ - wg: new(sync.WaitGroup), - fn: s.Evaluate, - out: l.val1, - } - - // evaluate the layer - p.X = l.base.X - - // Performance doesn't seem to improve past 100. - const batchSize = 100 - - eReq.p = make([]v3.Vec, 0, batchSize) - for x := 0; x < nx+1; x++ { - p.Y = l.base.Y - for y := 0; y < ny+1; y++ { - eReq.p = append(eReq.p, p) - if len(eReq.p) == batchSize { - eReq.wg.Add(1) - evalProcessCh <- eReq - eReq.out = eReq.out[batchSize:] // shift the output slice for processing - eReq.p = make([]v3.Vec, 0, batchSize) // create a new slice for the next batch - } - p.Y += dy - } - p.X += dx - } - - // send any remaining points for processing - if len(eReq.p) > 0 { - eReq.wg.Add(1) - evalProcessCh <- eReq - } - - // Wait for all processing to complete before returning - eReq.wg.Wait() -} - -func (l *layerXY) Get(x, y, z int) float64 { - idz := x*(l.steps.Y+1) + y - if z == 0 { - return l.val0[idz] - } - return l.val1[idz] -} - -//----------------------------------------------------------------------------- - // Specify the point to create the tetrahedra. // Point can be on edges or corners. // Index from 0 to 11 means an edge. diff --git a/render/marchfelogic.go b/render/marchfelogic.go index cd23fc600..6c09a72fa 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -17,23 +17,23 @@ func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape evalRoutines() // create the SDF layer cache - l := newLayerXY(base, inc, steps) - // evaluate the SDF for z = 0 + l := newLayerYZ(base, inc, steps) + // evaluate the SDF for x = 0 l.Evaluate(s, 0) nx, ny, nz := steps.X, steps.Y, steps.Z dx, dy, dz := inc.X, inc.Y, inc.Z var p v3.Vec - p.Z = base.Z - for z := 0; z < nz; z++ { - // read the z + 1 layer - l.Evaluate(s, z+1) - // process all cubes in the z and z + 1 layers - p.X = base.X - for x := 0; x < nx; x++ { - p.Y = base.Y - for y := 0; y < ny; y++ { + p.X = base.X + for x := 0; x < nx; x++ { + // read the x + 1 layer + l.Evaluate(s, x+1) + // process all cubes in the x and x + 1 layers + p.Y = base.Y + for y := 0; y < ny; y++ { + p.Z = base.Z + for z := 0; z < nz; z++ { x0, y0, z0 := p.X, p.Y, p.Z x1, y1, z1 := x0+dx, y0+dy, z0+dz corners := [8]v3.Vec{ @@ -46,21 +46,20 @@ func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape {x1, y1, z1}, {x0, y1, z1}} values := [8]float64{ - l.Get(x, y, 0), - l.Get(x+1, y, 0), - l.Get(x+1, y+1, 0), - l.Get(x, y+1, 0), - l.Get(x, y, 1), - l.Get(x+1, y, 1), - l.Get(x+1, y+1, 1), - l.Get(x, y+1, 1), - } + l.Get(0, y, z), + l.Get(1, y, z), + l.Get(1, y+1, z), + l.Get(0, y+1, z), + l.Get(0, y, z+1), + l.Get(1, y, z+1), + l.Get(1, y+1, z+1), + l.Get(0, y+1, z+1)} fes = append(fes, mcToFE(corners, values, x, y, z, order, shape)...) - p.Y += dy + p.Z += dz } - p.X += dx + p.Y += dy } - p.Z += dz + p.X += dx } return fes From c8bccc70e5282287e09f92c1f1a0baa91a54e6ab Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 25 Jul 2023 15:22:46 +0330 Subject: [PATCH 625/775] Make consistent with the last commit --- render/marchfe.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/render/marchfe.go b/render/marchfe.go index af73b73ff..d314ffeb0 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -99,24 +99,23 @@ func (r *MarchingCubesFEUniform) Voxels(s sdf.SDF3) (v3i.Vec, v3.Vec, []v3.Vec, maxs := make([]v3.Vec, 0, nz*nx*ny) var p v3.Vec - p.Z = base.Z - for z := 0; z < nz; z++ { - // all cubes in the z and z + 1 layers - p.X = base.X - for x := 0; x < nx; x++ { - p.Y = base.Y - for y := 0; y < ny; y++ { + p.X = base.X + for x := 0; x < nx; x++ { + p.Y = base.Y + for y := 0; y < ny; y++ { + p.Z = base.Z + for z := 0; z < nz; z++ { x0, y0, z0 := p.X, p.Y, p.Z x1, y1, z1 := x0+dx, y0+dy, z0+dz mins = append(mins, v3.Vec{X: x0, Y: y0, Z: z0}) maxs = append(maxs, v3.Vec{X: x1, Y: y1, Z: z1}) - p.Y += dy + p.Z += dz } - p.X += dx + p.Y += dy } - p.Z += dz + p.X += dx } return v3i.Vec{X: nx, Y: ny, Z: nz}, v3.Vec{X: dx, Y: dy, Z: dz}, mins, maxs From c531fa32a010c0d70b93e00b28614123249a5b35 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 25 Jul 2023 15:29:21 +0330 Subject: [PATCH 626/775] Make consistent: 1D to 3D index conversion --- render/finiteelements/buffer/voxel.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 553534708..35cf1d174 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -81,16 +81,16 @@ func NewVoxelGrid(len v3i.Vec, dim v3.Vec, mins, maxs []v3.Vec) *VoxelGrid { // This func must be consistent with `(r *MarchingCubesFEUniform) Voxels` func. // This func must be consistent with `marchingCubesFE` func too. func (vg *VoxelGrid) index1Dto3D(i int) (int, int, int) { - y := i % vg.Len.Y - x := (i / vg.Len.Y) % vg.Len.X - z := i / (vg.Len.Y * vg.Len.X) + z := i % vg.Len.Z + y := (i / vg.Len.Z) % vg.Len.Y + x := i / (vg.Len.Z * vg.Len.Y) return x, y, z } // This func must be consistent with `(r *MarchingCubesFEUniform) Voxels` func. // This func must be consistent with `marchingCubesFE` func too. func (vg *VoxelGrid) index3Dto1D(x, y, z int) int { - return z*vg.Len.X*vg.Len.Y + x*vg.Len.Y + y + return x*vg.Len.Y*vg.Len.Z + y*vg.Len.Z + z } func (vg *VoxelGrid) Size() (int, int, int) { From bcad753fa55c5499f5f42cab8351761177be510a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 11:34:40 +0330 Subject: [PATCH 627/775] Modify according to latest master changes --- examples/finite_elements/main.go | 8 +------- render/marchfehelper.go | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f5451cc8f..1a90131d8 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -108,14 +108,8 @@ func benchmarkRun( loads []*mesh.Load, elementconfig ElementConfig, ) { - // read the stl file. - file, err := os.OpenFile(stl, os.O_RDONLY, 0400) - if err != nil { - log.Fatalf("error: %s", err) - } - // create the SDF from the STL mesh - inSdf, err := obj.ImportSTL(file, 20, 3, 5) + inSdf, err := obj.ImportSTL(stl, 20, 3, 5) if err != nil { log.Fatalf("error: %s", err) } diff --git a/render/marchfehelper.go b/render/marchfehelper.go index 127bd4fce..44972d7bd 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -3,6 +3,7 @@ package render import ( "math" + "github.com/deadsy/sdfx/sdf" v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -282,31 +283,31 @@ func isBadTet10(coords [10]v3.Vec) (bool, float64) { func degenerateTriangles(a, b, c, d v3.Vec) bool { // 4 triangles are possible. // Each triangle is a tetrahedron side. - t := Triangle3{} - t.V[0] = a - t.V[1] = b - t.V[2] = c + t := sdf.Triangle3{} + t[0] = a + t[1] = b + t[2] = c // Use the epsilon value of `vertexbuffer.go` if t.Degenerate(0.0001) { return true } - t.V[0] = a - t.V[1] = b - t.V[2] = d + t[0] = a + t[1] = b + t[2] = d // Use the epsilon value of `vertexbuffer.go` if t.Degenerate(0.0001) { return true } - t.V[0] = a - t.V[1] = c - t.V[2] = d + t[0] = a + t[1] = c + t[2] = d // Use the epsilon value of `vertexbuffer.go` if t.Degenerate(0.0001) { return true } - t.V[0] = b - t.V[1] = c - t.V[2] = d + t[0] = b + t[1] = c + t[2] = d // Use the epsilon value of `vertexbuffer.go` return t.Degenerate(0.0001) } From 8e416a418f1fa4420aba2ec9045c64b3f831ecfb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 11:54:15 +0330 Subject: [PATCH 628/775] Comment --- examples/finite_elements/main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 1a90131d8..ec1ec00d1 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -86,9 +86,9 @@ func main() { case Pipe: restraints = benchmarkPipeRestraint() // When resolution is `50`, the pipe benchmark misses some necessary finite elements. - // By incrementing it to `51`, the problem is fixed. - // TODO: Why does resolution have a high sensitivity? - benchmarkRun("../../files/benchmark-pipe.stl", 51, 0, 3, restraints, loads, elementconfig) + // By incrementing it to `51`, no element is missed. + // There is a bug: https://github.com/deadsy/sdfx/issues/72 + benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads, elementconfig) case I: restraints = benchmarkIRestraint() benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads, elementconfig) From 1b3c439b87bc0d1dd3468c80b1dd7f0b7160973b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 12:04:04 +0330 Subject: [PATCH 629/775] Placeholder func to fix disconnections --- examples/finite_elements/main.go | 2 ++ render/finiteelements/mesh/disconnection.go | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 render/finiteelements/mesh/disconnection.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index ec1ec00d1..81b0f4329 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -218,6 +218,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) + m.Connect() // Write all layers of mesh to file. return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) @@ -233,6 +234,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) + m.Connect() // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) diff --git a/render/finiteelements/mesh/disconnection.go b/render/finiteelements/mesh/disconnection.go new file mode 100644 index 000000000..232f5ea46 --- /dev/null +++ b/render/finiteelements/mesh/disconnection.go @@ -0,0 +1,6 @@ +package mesh + +// Fix any disconnected finite elements. +// They cause FEA solver to throw error. +func (m *Fem) Connect() { +} From 01d1c3f03d4cb125a5ef117ffd97e517fb40d627 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 14:03:13 +0330 Subject: [PATCH 630/775] Count disconnected components --- examples/finite_elements/main.go | 6 +- render/finiteelements/buffer/graph.go | 74 +++++++++++++++++++++ render/finiteelements/mesh/disconnection.go | 5 +- 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 render/finiteelements/buffer/graph.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 81b0f4329..56a63a816 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -218,7 +218,8 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) - m.Connect() + components := m.Components() + fmt.Printf("components count: %v\n", components) // Write all layers of mesh to file. return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) @@ -234,7 +235,8 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) - m.Connect() + components := m.Components() + fmt.Printf("components count: %v\n", components) // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) diff --git a/render/finiteelements/buffer/graph.go b/render/finiteelements/buffer/graph.go new file mode 100644 index 000000000..638f4161a --- /dev/null +++ b/render/finiteelements/buffer/graph.go @@ -0,0 +1,74 @@ +package buffer + +type Graph struct { + adjacencyList map[*Voxel][]*Voxel +} + +func (g *Graph) AddEdge(v1, v2 *Voxel) { + // Add an edge from v1 to v2. A new element is created if v1 is not already in the map + g.adjacencyList[v1] = append(g.adjacencyList[v1], v2) + // Add an edge from v2 to v1. A new element is created if v2 is not already in the map + g.adjacencyList[v2] = append(g.adjacencyList[v2], v1) +} + +func NewGraph(vg *VoxelGrid) *Graph { + g := &Graph{ + adjacencyList: make(map[*Voxel][]*Voxel), + } + + // For each pair of voxels, check if they share a node and add an edge if they do + for i, v1 := range vg.Voxels { + for _, v2 := range vg.Voxels[i+1:] { + for _, e1 := range v1.data { + for _, e2 := range v2.data { + if sharesNode(e1, e2) { + g.AddEdge(v1, v2) + break + } + } + } + } + } + + return g +} + +// Check if two elements share a node +func sharesNode(e1, e2 *Element) bool { + for _, n1 := range e1.Nodes { + for _, n2 := range e2.Nodes { + if n1 == n2 { + return true + } + } + } + + return false +} + +// Perform a DFS on the voxel graph starting from voxel v +func DFS(g *Graph, v *Voxel, visited *map[*Voxel]bool) { + (*visited)[v] = true + + for _, neighbor := range g.adjacencyList[v] { + if !(*visited)[neighbor] { + DFS(g, neighbor, visited) + } + } +} + +// Returns the number of connected components in the voxel grid +func ConnectedComponents(vg *VoxelGrid) int { + g := NewGraph(vg) + visited := make(map[*Voxel]bool) + components := 0 + + for _, v := range vg.Voxels { + if !visited[v] { + components++ + DFS(g, v, &visited) + } + } + + return components +} diff --git a/render/finiteelements/mesh/disconnection.go b/render/finiteelements/mesh/disconnection.go index 232f5ea46..43d4e6ad9 100644 --- a/render/finiteelements/mesh/disconnection.go +++ b/render/finiteelements/mesh/disconnection.go @@ -1,6 +1,9 @@ package mesh +import "github.com/deadsy/sdfx/render/finiteelements/buffer" + // Fix any disconnected finite elements. // They cause FEA solver to throw error. -func (m *Fem) Connect() { +func (m *Fem) Components() int { + return buffer.ConnectedComponents(m.IBuff.Grid) } From 134a8c0d4fe7d4cb0229458d3d8474e832566895 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 14:39:57 +0330 Subject: [PATCH 631/775] Revert "Count disconnected components" This reverts commit 01d1c3f03d4cb125a5ef117ffd97e517fb40d627. --- examples/finite_elements/main.go | 6 +- render/finiteelements/buffer/graph.go | 74 --------------------- render/finiteelements/mesh/disconnection.go | 5 +- 3 files changed, 3 insertions(+), 82 deletions(-) delete mode 100644 render/finiteelements/buffer/graph.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 56a63a816..81b0f4329 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -218,8 +218,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) - components := m.Components() - fmt.Printf("components count: %v\n", components) + m.Connect() // Write all layers of mesh to file. return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) @@ -235,8 +234,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) - components := m.Components() - fmt.Printf("components count: %v\n", components) + m.Connect() // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) diff --git a/render/finiteelements/buffer/graph.go b/render/finiteelements/buffer/graph.go deleted file mode 100644 index 638f4161a..000000000 --- a/render/finiteelements/buffer/graph.go +++ /dev/null @@ -1,74 +0,0 @@ -package buffer - -type Graph struct { - adjacencyList map[*Voxel][]*Voxel -} - -func (g *Graph) AddEdge(v1, v2 *Voxel) { - // Add an edge from v1 to v2. A new element is created if v1 is not already in the map - g.adjacencyList[v1] = append(g.adjacencyList[v1], v2) - // Add an edge from v2 to v1. A new element is created if v2 is not already in the map - g.adjacencyList[v2] = append(g.adjacencyList[v2], v1) -} - -func NewGraph(vg *VoxelGrid) *Graph { - g := &Graph{ - adjacencyList: make(map[*Voxel][]*Voxel), - } - - // For each pair of voxels, check if they share a node and add an edge if they do - for i, v1 := range vg.Voxels { - for _, v2 := range vg.Voxels[i+1:] { - for _, e1 := range v1.data { - for _, e2 := range v2.data { - if sharesNode(e1, e2) { - g.AddEdge(v1, v2) - break - } - } - } - } - } - - return g -} - -// Check if two elements share a node -func sharesNode(e1, e2 *Element) bool { - for _, n1 := range e1.Nodes { - for _, n2 := range e2.Nodes { - if n1 == n2 { - return true - } - } - } - - return false -} - -// Perform a DFS on the voxel graph starting from voxel v -func DFS(g *Graph, v *Voxel, visited *map[*Voxel]bool) { - (*visited)[v] = true - - for _, neighbor := range g.adjacencyList[v] { - if !(*visited)[neighbor] { - DFS(g, neighbor, visited) - } - } -} - -// Returns the number of connected components in the voxel grid -func ConnectedComponents(vg *VoxelGrid) int { - g := NewGraph(vg) - visited := make(map[*Voxel]bool) - components := 0 - - for _, v := range vg.Voxels { - if !visited[v] { - components++ - DFS(g, v, &visited) - } - } - - return components -} diff --git a/render/finiteelements/mesh/disconnection.go b/render/finiteelements/mesh/disconnection.go index 43d4e6ad9..232f5ea46 100644 --- a/render/finiteelements/mesh/disconnection.go +++ b/render/finiteelements/mesh/disconnection.go @@ -1,9 +1,6 @@ package mesh -import "github.com/deadsy/sdfx/render/finiteelements/buffer" - // Fix any disconnected finite elements. // They cause FEA solver to throw error. -func (m *Fem) Components() int { - return buffer.ConnectedComponents(m.IBuff.Grid) +func (m *Fem) Connect() { } From 2bdce111a0ec3c5baedd0a2b35b3ce37b429b5e1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 15:22:47 +0330 Subject: [PATCH 632/775] Rename --- examples/finite_elements/main.go | 6 ++++-- render/finiteelements/mesh/disconnection.go | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 81b0f4329..5bfdf233e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -218,7 +218,8 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) - m.Connect() + components := m.CountComponents() + fmt.Printf("components count: %v\n", components) // Write all layers of mesh to file. return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) @@ -234,7 +235,8 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) - m.Connect() + components := m.CountComponents() + fmt.Printf("components count: %v\n", components) // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) diff --git a/render/finiteelements/mesh/disconnection.go b/render/finiteelements/mesh/disconnection.go index 232f5ea46..4093d20c5 100644 --- a/render/finiteelements/mesh/disconnection.go +++ b/render/finiteelements/mesh/disconnection.go @@ -1,6 +1,7 @@ package mesh -// Fix any disconnected finite elements. +// Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. -func (m *Fem) Connect() { +func (m *Fem) CountComponents() int { + return 0 } From dfe93db72be7eb345e611811048f3c2fc962c55a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 15:35:18 +0330 Subject: [PATCH 633/775] Remove extra file --- render/finiteelements/mesh/disconnection.go | 7 ------- render/finiteelements/mesh/fem.go | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 7 deletions(-) delete mode 100644 render/finiteelements/mesh/disconnection.go diff --git a/render/finiteelements/mesh/disconnection.go b/render/finiteelements/mesh/disconnection.go deleted file mode 100644 index 4093d20c5..000000000 --- a/render/finiteelements/mesh/disconnection.go +++ /dev/null @@ -1,7 +0,0 @@ -package mesh - -// Count separate components consisting of disconnected finite elements. -// They cause FEA solver to throw error. -func (m *Fem) CountComponents() int { - return 0 -} diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index a9610f851..78820c398 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -129,6 +129,20 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { return m.IBuff.Grid.VoxelsIntersecting(points) } +//----------------------------------------------------------------------------- + +// Count separate components consisting of disconnected finite elements. +// They cause FEA solver to throw error. +func (m *Fem) CountComponents() int { + process := func(x, y, z int, els []*buffer.Element) { + } + + m.iterate(process) + return 0 +} + +//----------------------------------------------------------------------------- + // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. func (m *Fem) WriteInp( path string, From 1ed0b7299875c98b28be294f07d3f5560d32e686 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 15:38:18 +0330 Subject: [PATCH 634/775] Count disconnected components: at voxel grid level --- render/finiteelements/buffer/voxel.go | 10 ++++++++++ render/finiteelements/mesh/fem.go | 6 +----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 35cf1d174..cf91bb5e2 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -166,3 +166,13 @@ func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { } } } + +//----------------------------------------------------------------------------- + +// Count separate components consisting of disconnected finite elements. +// They cause FEA solver to throw error. +func (vg *VoxelGrid) CountComponents() int { + return 0 +} + +//----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 78820c398..7e72fad1d 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -134,11 +134,7 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. func (m *Fem) CountComponents() int { - process := func(x, y, z int, els []*buffer.Element) { - } - - m.iterate(process) - return 0 + return m.IBuff.Grid.CountComponents() } //----------------------------------------------------------------------------- From 792104d951cb7a3e5e214c74569820648e70d616 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 15:40:47 +0330 Subject: [PATCH 635/775] Revert "Count disconnected components: at voxel grid level" This reverts commit 1ed0b7299875c98b28be294f07d3f5560d32e686. --- render/finiteelements/buffer/voxel.go | 10 ---------- render/finiteelements/mesh/fem.go | 6 +++++- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index cf91bb5e2..35cf1d174 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -166,13 +166,3 @@ func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { } } } - -//----------------------------------------------------------------------------- - -// Count separate components consisting of disconnected finite elements. -// They cause FEA solver to throw error. -func (vg *VoxelGrid) CountComponents() int { - return 0 -} - -//----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 7e72fad1d..78820c398 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -134,7 +134,11 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. func (m *Fem) CountComponents() int { - return m.IBuff.Grid.CountComponents() + process := func(x, y, z int, els []*buffer.Element) { + } + + m.iterate(process) + return 0 } //----------------------------------------------------------------------------- From 8281a1899ad9096ff898d0785c58aa1dac91280a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 16:34:34 +0330 Subject: [PATCH 636/775] Try breadth-first search (BFS) for disconnections --- render/finiteelements/mesh/fem.go | 47 +++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 78820c398..a46d06db0 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -134,11 +134,54 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. func (m *Fem) CountComponents() int { + // Map key is (x, y, z) index of voxel. + visited := make(map[[3]int]bool, m.IBuff.Grid.Len.X*m.IBuff.Grid.Len.Y*m.IBuff.Grid.Len.Z) + count := 0 process := func(x, y, z int, els []*buffer.Element) { + if !visited[[3]int{x, y, z}] { + count++ + m.bfs(visited, [3]int{x, y, z}) + } } - m.iterate(process) - return 0 + return count +} + +func (m *Fem) bfs(visited map[[3]int]bool, start [3]int) { + queue := [][3]int{start} + visited[start] = true + + for len(queue) > 0 { + v := queue[0] + queue = queue[1:] + + neighbors := make([][3]int, 0) + for i := -1; i <= +1; i++ { + for j := -1; j <= +1; j++ { + for k := -1; k <= +1; k++ { + x := v[0] + i + y := v[1] + j + z := v[2] + k + if x >= 0 && x < m.IBuff.Grid.Len.X && + y >= 0 && y < m.IBuff.Grid.Len.Y && + z >= 0 && z < m.IBuff.Grid.Len.Z { + if x != v[0] && y != v[1] && z != v[2] { + // Overlapping voxel. + } else { + neighbors = append(neighbors, [3]int{x, y, z}) + } + } + } + } + } + + for _, n := range neighbors { + if !visited[n] { + visited[n] = true + queue = append(queue, n) + } + } + } } //----------------------------------------------------------------------------- From 0c93f231393d27be352a9e9755b8db713eaadcbe Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 16:55:09 +0330 Subject: [PATCH 637/775] New func to get neighbor voxels --- render/finiteelements/mesh/fem.go | 51 +++++++++++++++++++------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index a46d06db0..ef22f0d1c 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -155,25 +155,7 @@ func (m *Fem) bfs(visited map[[3]int]bool, start [3]int) { v := queue[0] queue = queue[1:] - neighbors := make([][3]int, 0) - for i := -1; i <= +1; i++ { - for j := -1; j <= +1; j++ { - for k := -1; k <= +1; k++ { - x := v[0] + i - y := v[1] + j - z := v[2] + k - if x >= 0 && x < m.IBuff.Grid.Len.X && - y >= 0 && y < m.IBuff.Grid.Len.Y && - z >= 0 && z < m.IBuff.Grid.Len.Z { - if x != v[0] && y != v[1] && z != v[2] { - // Overlapping voxel. - } else { - neighbors = append(neighbors, [3]int{x, y, z}) - } - } - } - } - } + neighbors := m.getNeighbors(v) for _, n := range neighbors { if !visited[n] { @@ -184,6 +166,37 @@ func (m *Fem) bfs(visited map[[3]int]bool, start [3]int) { } } +// It returns a list of neighbor voxels that are full, i.e. not empty. +func (m *Fem) getNeighbors(v [3]int) [][3]int { + var neighbors [][3]int + for i := -1; i <= 1; i++ { + for j := -1; j <= 1; j++ { + for k := -1; k <= 1; k++ { + if i == 0 && j == 0 && k == 0 { + continue + } + + x := v[0] + i + y := v[1] + j + z := v[2] + k + + if x >= 0 && x < m.IBuff.Grid.Len.X && + y >= 0 && y < m.IBuff.Grid.Len.Y && + z >= 0 && z < m.IBuff.Grid.Len.Z { + // Index is valid. + } else { + continue + } + + if len(m.IBuff.Grid.Get(x, y, z)) > 0 { + neighbors = append(neighbors, [3]int{x, y, z}) + } + } + } + } + return neighbors +} + //----------------------------------------------------------------------------- // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. From 9c36a2c9415f8ce33cd97bbfb7f72addeaec2ef0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 16:58:41 +0330 Subject: [PATCH 638/775] Comment --- render/finiteelements/mesh/fem.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index ef22f0d1c..8244f4e1f 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -188,6 +188,7 @@ func (m *Fem) getNeighbors(v [3]int) [][3]int { continue } + // Is neighbor voxel empty or not? if len(m.IBuff.Grid.Get(x, y, z)) > 0 { neighbors = append(neighbors, [3]int{x, y, z}) } From 46512a1fbb715316095b8183a1685a84abbb5104 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 17:02:42 +0330 Subject: [PATCH 639/775] New file --- render/finiteelements/mesh/disconnection.go | 72 +++++++++++++++++++++ render/finiteelements/mesh/fem.go | 69 -------------------- 2 files changed, 72 insertions(+), 69 deletions(-) create mode 100644 render/finiteelements/mesh/disconnection.go diff --git a/render/finiteelements/mesh/disconnection.go b/render/finiteelements/mesh/disconnection.go new file mode 100644 index 000000000..71690fc25 --- /dev/null +++ b/render/finiteelements/mesh/disconnection.go @@ -0,0 +1,72 @@ +package mesh + +import "github.com/deadsy/sdfx/render/finiteelements/buffer" + +// Count separate components consisting of disconnected finite elements. +// They cause FEA solver to throw error. +func (m *Fem) CountComponents() int { + // Map key is (x, y, z) index of voxel. + visited := make(map[[3]int]bool, m.IBuff.Grid.Len.X*m.IBuff.Grid.Len.Y*m.IBuff.Grid.Len.Z) + count := 0 + process := func(x, y, z int, els []*buffer.Element) { + if !visited[[3]int{x, y, z}] { + count++ + m.bfs(visited, [3]int{x, y, z}) + } + } + m.iterate(process) + return count +} + +func (m *Fem) bfs(visited map[[3]int]bool, start [3]int) { + queue := [][3]int{start} + visited[start] = true + + for len(queue) > 0 { + v := queue[0] + queue = queue[1:] + + neighbors := m.getNeighbors(v) + + for _, n := range neighbors { + if !visited[n] { + visited[n] = true + queue = append(queue, n) + } + } + } +} + +// It returns a list of neighbor voxels that are full, i.e. not empty. +func (m *Fem) getNeighbors(v [3]int) [][3]int { + var neighbors [][3]int + for i := -1; i <= 1; i++ { + for j := -1; j <= 1; j++ { + for k := -1; k <= 1; k++ { + if i == 0 && j == 0 && k == 0 { + continue + } + + x := v[0] + i + y := v[1] + j + z := v[2] + k + + if x >= 0 && x < m.IBuff.Grid.Len.X && + y >= 0 && y < m.IBuff.Grid.Len.Y && + z >= 0 && z < m.IBuff.Grid.Len.Z { + // Index is valid. + } else { + continue + } + + // Is neighbor voxel empty or not? + if len(m.IBuff.Grid.Get(x, y, z)) > 0 { + neighbors = append(neighbors, [3]int{x, y, z}) + } + } + } + } + return neighbors +} + +//----------------------------------------------------------------------------- diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 8244f4e1f..6198b670a 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -131,75 +131,6 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { //----------------------------------------------------------------------------- -// Count separate components consisting of disconnected finite elements. -// They cause FEA solver to throw error. -func (m *Fem) CountComponents() int { - // Map key is (x, y, z) index of voxel. - visited := make(map[[3]int]bool, m.IBuff.Grid.Len.X*m.IBuff.Grid.Len.Y*m.IBuff.Grid.Len.Z) - count := 0 - process := func(x, y, z int, els []*buffer.Element) { - if !visited[[3]int{x, y, z}] { - count++ - m.bfs(visited, [3]int{x, y, z}) - } - } - m.iterate(process) - return count -} - -func (m *Fem) bfs(visited map[[3]int]bool, start [3]int) { - queue := [][3]int{start} - visited[start] = true - - for len(queue) > 0 { - v := queue[0] - queue = queue[1:] - - neighbors := m.getNeighbors(v) - - for _, n := range neighbors { - if !visited[n] { - visited[n] = true - queue = append(queue, n) - } - } - } -} - -// It returns a list of neighbor voxels that are full, i.e. not empty. -func (m *Fem) getNeighbors(v [3]int) [][3]int { - var neighbors [][3]int - for i := -1; i <= 1; i++ { - for j := -1; j <= 1; j++ { - for k := -1; k <= 1; k++ { - if i == 0 && j == 0 && k == 0 { - continue - } - - x := v[0] + i - y := v[1] + j - z := v[2] + k - - if x >= 0 && x < m.IBuff.Grid.Len.X && - y >= 0 && y < m.IBuff.Grid.Len.Y && - z >= 0 && z < m.IBuff.Grid.Len.Z { - // Index is valid. - } else { - continue - } - - // Is neighbor voxel empty or not? - if len(m.IBuff.Grid.Get(x, y, z)) > 0 { - neighbors = append(neighbors, [3]int{x, y, z}) - } - } - } - } - return neighbors -} - -//----------------------------------------------------------------------------- - // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. func (m *Fem) WriteInp( path string, From 565e5b547b6c3fba88fa6112f9bf02af699b9370 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 17:20:49 +0330 Subject: [PATCH 640/775] Move logic to voxel package --- .../{mesh => buffer}/disconnection.go | 37 ++++++++++--------- render/finiteelements/mesh/fem.go | 8 ++++ 2 files changed, 28 insertions(+), 17 deletions(-) rename render/finiteelements/{mesh => buffer}/disconnection.go (58%) diff --git a/render/finiteelements/mesh/disconnection.go b/render/finiteelements/buffer/disconnection.go similarity index 58% rename from render/finiteelements/mesh/disconnection.go rename to render/finiteelements/buffer/disconnection.go index 71690fc25..51a0508de 100644 --- a/render/finiteelements/mesh/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -1,24 +1,27 @@ -package mesh - -import "github.com/deadsy/sdfx/render/finiteelements/buffer" +package buffer // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. -func (m *Fem) CountComponents() int { +func (vg *VoxelGrid) CountComponents() int { // Map key is (x, y, z) index of voxel. - visited := make(map[[3]int]bool, m.IBuff.Grid.Len.X*m.IBuff.Grid.Len.Y*m.IBuff.Grid.Len.Z) + visited := make(map[[3]int]bool, vg.Len.X*vg.Len.Y*vg.Len.Z) count := 0 - process := func(x, y, z int, els []*buffer.Element) { - if !visited[[3]int{x, y, z}] { - count++ - m.bfs(visited, [3]int{x, y, z}) + for z := 0; z < vg.Len.Z; z++ { + for y := 0; y < vg.Len.Y; y++ { + for x := 0; x < vg.Len.X; x++ { + if !visited[[3]int{x, y, z}] { + count++ + vg.bfs(visited, [3]int{x, y, z}) + } + } } } - m.iterate(process) return count } -func (m *Fem) bfs(visited map[[3]int]bool, start [3]int) { +// Algorithm: breadth-first search (BFS). +// This is much faster than depth first search (DFS) algorithm. +func (vg *VoxelGrid) bfs(visited map[[3]int]bool, start [3]int) { queue := [][3]int{start} visited[start] = true @@ -26,7 +29,7 @@ func (m *Fem) bfs(visited map[[3]int]bool, start [3]int) { v := queue[0] queue = queue[1:] - neighbors := m.getNeighbors(v) + neighbors := vg.getNeighbors(v) for _, n := range neighbors { if !visited[n] { @@ -38,7 +41,7 @@ func (m *Fem) bfs(visited map[[3]int]bool, start [3]int) { } // It returns a list of neighbor voxels that are full, i.e. not empty. -func (m *Fem) getNeighbors(v [3]int) [][3]int { +func (vg *VoxelGrid) getNeighbors(v [3]int) [][3]int { var neighbors [][3]int for i := -1; i <= 1; i++ { for j := -1; j <= 1; j++ { @@ -51,16 +54,16 @@ func (m *Fem) getNeighbors(v [3]int) [][3]int { y := v[1] + j z := v[2] + k - if x >= 0 && x < m.IBuff.Grid.Len.X && - y >= 0 && y < m.IBuff.Grid.Len.Y && - z >= 0 && z < m.IBuff.Grid.Len.Z { + if x >= 0 && x < vg.Len.X && + y >= 0 && y < vg.Len.Y && + z >= 0 && z < vg.Len.Z { // Index is valid. } else { continue } // Is neighbor voxel empty or not? - if len(m.IBuff.Grid.Get(x, y, z)) > 0 { + if len(vg.Get(x, y, z)) > 0 { neighbors = append(neighbors, [3]int{x, y, z}) } } diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 6198b670a..7e72fad1d 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -131,6 +131,14 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { //----------------------------------------------------------------------------- +// Count separate components consisting of disconnected finite elements. +// They cause FEA solver to throw error. +func (m *Fem) CountComponents() int { + return m.IBuff.Grid.CountComponents() +} + +//----------------------------------------------------------------------------- + // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. func (m *Fem) WriteInp( path string, From 247372d36aac5b18222fe3833cdc243b1a186b10 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 2 Aug 2023 17:31:19 +0330 Subject: [PATCH 641/775] Simplify map declaration --- render/finiteelements/buffer/disconnection.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 51a0508de..0a8362be5 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -4,7 +4,7 @@ package buffer // They cause FEA solver to throw error. func (vg *VoxelGrid) CountComponents() int { // Map key is (x, y, z) index of voxel. - visited := make(map[[3]int]bool, vg.Len.X*vg.Len.Y*vg.Len.Z) + visited := make(map[[3]int]bool) count := 0 for z := 0; z < vg.Len.Z; z++ { for y := 0; y < vg.Len.Y; y++ { From 5dd3e6d67b012d5c1a60825a2c9372bdfa0679ef Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 11:28:17 +0330 Subject: [PATCH 642/775] Fix: check if a voxel is not empty --- render/finiteelements/buffer/disconnection.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 0a8362be5..8f3f8607a 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -9,7 +9,8 @@ func (vg *VoxelGrid) CountComponents() int { for z := 0; z < vg.Len.Z; z++ { for y := 0; y < vg.Len.Y; y++ { for x := 0; x < vg.Len.X; x++ { - if !visited[[3]int{x, y, z}] { + // If voxel is not empty and if it's not already visited. + if len(vg.Get(x, y, z)) > 0 && !visited[[3]int{x, y, z}] { count++ vg.bfs(visited, [3]int{x, y, z}) } From 47d5c2bd5c4a9771d734778260bfca464e157d18 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 12:55:21 +0330 Subject: [PATCH 643/775] Simplify neighbor logic --- render/finiteelements/buffer/disconnection.go | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 8f3f8607a..777429725 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -44,32 +44,34 @@ func (vg *VoxelGrid) bfs(visited map[[3]int]bool, start [3]int) { // It returns a list of neighbor voxels that are full, i.e. not empty. func (vg *VoxelGrid) getNeighbors(v [3]int) [][3]int { var neighbors [][3]int - for i := -1; i <= 1; i++ { - for j := -1; j <= 1; j++ { - for k := -1; k <= 1; k++ { - if i == 0 && j == 0 && k == 0 { - continue - } - x := v[0] + i - y := v[1] + j - z := v[2] + k + // The 3D directions to iterate over + directions := [][3]int{ + {1, 0, 0}, + {-1, 0, 0}, + {0, 1, 0}, + {0, -1, 0}, + {0, 0, 1}, + {0, 0, -1}, + } - if x >= 0 && x < vg.Len.X && - y >= 0 && y < vg.Len.Y && - z >= 0 && z < vg.Len.Z { - // Index is valid. - } else { - continue - } + for _, direction := range directions { + x := v[0] + direction[0] + y := v[1] + direction[1] + z := v[2] + direction[2] - // Is neighbor voxel empty or not? - if len(vg.Get(x, y, z)) > 0 { - neighbors = append(neighbors, [3]int{x, y, z}) - } - } + if x >= 0 && x < vg.Len.X && y >= 0 && y < vg.Len.Y && z >= 0 && z < vg.Len.Z { + // Index is valid. + } else { + continue + } + + // Is neighbor voxel non-empty? + if len(vg.Get(x, y, z)) > 0 { + neighbors = append(neighbors, [3]int{x, y, z}) } } + return neighbors } From abfb0fb8f59428da6890c544975480651d2653da Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 13:02:34 +0330 Subject: [PATCH 644/775] New func to check voxel index validity --- render/finiteelements/buffer/disconnection.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 777429725..3ceff9b5d 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -45,7 +45,9 @@ func (vg *VoxelGrid) bfs(visited map[[3]int]bool, start [3]int) { func (vg *VoxelGrid) getNeighbors(v [3]int) [][3]int { var neighbors [][3]int - // The 3D directions to iterate over + // The 3D directions to iterate over. + // Two voxels are considered neighbors if they share a face, + // i.e., they are adjacent along x, y, or z direction. directions := [][3]int{ {1, 0, 0}, {-1, 0, 0}, @@ -60,9 +62,7 @@ func (vg *VoxelGrid) getNeighbors(v [3]int) [][3]int { y := v[1] + direction[1] z := v[2] + direction[2] - if x >= 0 && x < vg.Len.X && y >= 0 && y < vg.Len.Y && z >= 0 && z < vg.Len.Z { - // Index is valid. - } else { + if !vg.isValid(x, y, z) { continue } @@ -75,4 +75,9 @@ func (vg *VoxelGrid) getNeighbors(v [3]int) [][3]int { return neighbors } +// Is voxel index inside a valid range? +func (vg *VoxelGrid) isValid(x, y, z int) bool { + return x >= 0 && y >= 0 && z >= 0 && x < vg.Len.X && y < vg.Len.Y && z < vg.Len.Z +} + //----------------------------------------------------------------------------- From 2c1c3bea5913037807d848b51c51e2f3cfc629a1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 13:18:45 +0330 Subject: [PATCH 645/775] Rename --- render/finiteelements/buffer/disconnection.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 3ceff9b5d..c65f977bc 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -30,7 +30,7 @@ func (vg *VoxelGrid) bfs(visited map[[3]int]bool, start [3]int) { v := queue[0] queue = queue[1:] - neighbors := vg.getNeighbors(v) + neighbors := vg.nonemptyNeighbors(v) for _, n := range neighbors { if !visited[n] { @@ -41,8 +41,8 @@ func (vg *VoxelGrid) bfs(visited map[[3]int]bool, start [3]int) { } } -// It returns a list of neighbor voxels that are full, i.e. not empty. -func (vg *VoxelGrid) getNeighbors(v [3]int) [][3]int { +// It returns a list of neighbor voxels that are non-empty. +func (vg *VoxelGrid) nonemptyNeighbors(v [3]int) [][3]int { var neighbors [][3]int // The 3D directions to iterate over. From 02bccb6b06bc68bc4aad3ac2836e7f3e05e6952e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 15:07:02 +0330 Subject: [PATCH 646/775] New file: BFS element-by-element --- .../buffer/disconnection_ele.go | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 render/finiteelements/buffer/disconnection_ele.go diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go new file mode 100644 index 000000000..77ec96742 --- /dev/null +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -0,0 +1,78 @@ +package buffer + +// Count separate components consisting of disconnected finite elements. +// They cause FEA solver to throw error. +func (vg *VoxelGrid) Components() int { + // Map key is (x, y, z) index of voxel. + visited := make(map[[3]int]bool) + count := 0 + for z := 0; z < vg.Len.Z; z++ { + for y := 0; y < vg.Len.Y; y++ { + for x := 0; x < vg.Len.X; x++ { + // If voxel is not empty and if it's not already visited. + if len(vg.Get(x, y, z)) > 0 && !visited[[3]int{x, y, z}] { + count++ + vg.BFS(visited, [3]int{x, y, z}) + } + } + } + } + return count +} + +// Algorithm: breadth-first search (BFS). +// This is much faster than depth first search (DFS) algorithm. +func (vg *VoxelGrid) BFS(visited map[[3]int]bool, start [3]int) { + queue := [][3]int{start} + visited[start] = true + + for len(queue) > 0 { + v := queue[0] + queue = queue[1:] + + neighbors := vg.nonemptyNeighbors(v) + + for _, n := range neighbors { + if !visited[n] { + visited[n] = true + queue = append(queue, n) + } + } + } +} + +// It returns a list of neighbors. +func (vg *VoxelGrid) neighbors(v [3]int) [][3]int { + var neighbors [][3]int + + // The 3D directions to iterate over. + // Two voxels are considered neighbors if they share a face, + // i.e., they are adjacent along x, y, or z direction. + directions := [][3]int{ + {1, 0, 0}, + {-1, 0, 0}, + {0, 1, 0}, + {0, -1, 0}, + {0, 0, 1}, + {0, 0, -1}, + } + + for _, direction := range directions { + x := v[0] + direction[0] + y := v[1] + direction[1] + z := v[2] + direction[2] + + if !vg.isValid(x, y, z) { + continue + } + + // Is neighbor voxel non-empty? + if len(vg.Get(x, y, z)) > 0 { + neighbors = append(neighbors, [3]int{x, y, z}) + } + } + + return neighbors +} + +//----------------------------------------------------------------------------- From baae2caeb2d3dc1424f90b2b7f00d1a93baf84af Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 15:09:16 +0330 Subject: [PATCH 647/775] Rename func --- render/finiteelements/buffer/disconnection.go | 2 +- render/finiteelements/mesh/fem.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index c65f977bc..9f6e0fc9c 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -2,7 +2,7 @@ package buffer // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. -func (vg *VoxelGrid) CountComponents() int { +func (vg *VoxelGrid) VoxelComponents() int { // Map key is (x, y, z) index of voxel. visited := make(map[[3]int]bool) count := 0 diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 7e72fad1d..12c3e7d23 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -134,7 +134,7 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. func (m *Fem) CountComponents() int { - return m.IBuff.Grid.CountComponents() + return m.IBuff.Grid.VoxelComponents() } //----------------------------------------------------------------------------- From f711267ff5ffb6295f2a78b53dfd0664ceb411b7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 15:12:20 +0330 Subject: [PATCH 648/775] Fix func call --- render/finiteelements/buffer/disconnection_ele.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 77ec96742..54d53f90c 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -30,7 +30,7 @@ func (vg *VoxelGrid) BFS(visited map[[3]int]bool, start [3]int) { v := queue[0] queue = queue[1:] - neighbors := vg.nonemptyNeighbors(v) + neighbors := vg.neighbors(v) for _, n := range neighbors { if !visited[n] { From 4b8dd71ccc91c4aedf4986ddf24c7704b740fc3e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 15:13:20 +0330 Subject: [PATCH 649/775] Fix func call --- render/finiteelements/mesh/fem.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 12c3e7d23..44a6cb7f7 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -134,7 +134,7 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. func (m *Fem) CountComponents() int { - return m.IBuff.Grid.VoxelComponents() + return m.IBuff.Grid.Components() } //----------------------------------------------------------------------------- From a3e65bc654604ea06ef41f64b8203d24c17c607d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 15:14:13 +0330 Subject: [PATCH 650/775] Comment --- render/finiteelements/buffer/disconnection.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 9f6e0fc9c..16376a5e0 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -1,7 +1,6 @@ package buffer -// Count separate components consisting of disconnected finite elements. -// They cause FEA solver to throw error. +// Count separate components consisting of disconnected voxels. func (vg *VoxelGrid) VoxelComponents() int { // Map key is (x, y, z) index of voxel. visited := make(map[[3]int]bool) From db1bb22d05e2cd938b0397a43642f584a3fe77a1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 15:57:27 +0330 Subject: [PATCH 651/775] Comment --- render/finiteelements/buffer/disconnection.go | 1 - 1 file changed, 1 deletion(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 16376a5e0..7038926c4 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -20,7 +20,6 @@ func (vg *VoxelGrid) VoxelComponents() int { } // Algorithm: breadth-first search (BFS). -// This is much faster than depth first search (DFS) algorithm. func (vg *VoxelGrid) bfs(visited map[[3]int]bool, start [3]int) { queue := [][3]int{start} visited[start] = true From 78383c8d498dd5171a40e940b4f34971119dea31 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 16:20:14 +0330 Subject: [PATCH 652/775] Element-by-element BFS --- .../buffer/disconnection_ele.go | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 54d53f90c..c55ee3a98 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -4,15 +4,17 @@ package buffer // They cause FEA solver to throw error. func (vg *VoxelGrid) Components() int { // Map key is (x, y, z) index of voxel. - visited := make(map[[3]int]bool) + visited := make(map[*Element]bool) count := 0 for z := 0; z < vg.Len.Z; z++ { for y := 0; y < vg.Len.Y; y++ { for x := 0; x < vg.Len.X; x++ { - // If voxel is not empty and if it's not already visited. - if len(vg.Get(x, y, z)) > 0 && !visited[[3]int{x, y, z}] { - count++ - vg.BFS(visited, [3]int{x, y, z}) + els := vg.Get(x, y, z) + for _, el := range els { + if !visited[el] { + count++ + vg.BFS(visited, el, [3]int{x, y, z}) + } } } } @@ -21,16 +23,15 @@ func (vg *VoxelGrid) Components() int { } // Algorithm: breadth-first search (BFS). -// This is much faster than depth first search (DFS) algorithm. -func (vg *VoxelGrid) BFS(visited map[[3]int]bool, start [3]int) { - queue := [][3]int{start} +func (vg *VoxelGrid) BFS(visited map[*Element]bool, start *Element, v [3]int) { + queue := []*Element{start} visited[start] = true for len(queue) > 0 { - v := queue[0] + e := queue[0] queue = queue[1:] - neighbors := vg.neighbors(v) + neighbors := vg.neighbors(e, v) for _, n := range neighbors { if !visited[n] { @@ -42,8 +43,8 @@ func (vg *VoxelGrid) BFS(visited map[[3]int]bool, start [3]int) { } // It returns a list of neighbors. -func (vg *VoxelGrid) neighbors(v [3]int) [][3]int { - var neighbors [][3]int +func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { + var neighbors []*Element // The 3D directions to iterate over. // Two voxels are considered neighbors if they share a face, @@ -66,13 +67,35 @@ func (vg *VoxelGrid) neighbors(v [3]int) [][3]int { continue } - // Is neighbor voxel non-empty? - if len(vg.Get(x, y, z)) > 0 { - neighbors = append(neighbors, [3]int{x, y, z}) + for _, el := range vg.Get(x, y, z) { + if sharesNode(e, el) { + neighbors = append(neighbors, el) + } } } return neighbors } +func sharesNode(e1, e2 *Element) bool { + if len(e1.Nodes) != len(e2.Nodes) { + return false + } + for _, n1 := range e1.Nodes { + if contains(e2.Nodes, n1) { + return true + } + } + return false +} + +func contains(arr []uint32, i uint32) bool { + for _, n := range arr { + if n == i { + return true + } + } + return false +} + //----------------------------------------------------------------------------- From 0544f74eb42faefaef5d7ed763b2af22a73db339 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 16:38:14 +0330 Subject: [PATCH 653/775] Comment --- render/finiteelements/buffer/disconnection_ele.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index c55ee3a98..877b1d8e8 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -47,8 +47,13 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { var neighbors []*Element // The 3D directions to iterate over. - // Two voxels are considered neighbors if they share a face, - // i.e., they are adjacent along x, y, or z direction. + // + // Two voxels could be considered neighbors if: + // 1) They share a face. + // 2) They share an edge. + // 3) They share a corner. + // + // You'll need to adjust: directions := [][3]int{ {1, 0, 0}, {-1, 0, 0}, From e7ca09b0af63f0ee52067d73812c14c63ce942f8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 16:41:40 +0330 Subject: [PATCH 654/775] TODO --- render/finiteelements/buffer/disconnection_ele.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 877b1d8e8..68443026f 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -55,12 +55,15 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { // // You'll need to adjust: directions := [][3]int{ + // Share a face: {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}, + // Share an edge: + // TODO. } for _, direction := range directions { From 7cc2c1ad2bc7ee1c7d844a3d3fb83329bef7062e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 16:51:19 +0330 Subject: [PATCH 655/775] Complete the TODO --- render/finiteelements/buffer/disconnection_ele.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 68443026f..53a29df73 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -63,7 +63,19 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { {0, 0, 1}, {0, 0, -1}, // Share an edge: - // TODO. + {1, 1, 0}, + {1, -1, 0}, + {-1, 1, 0}, + {-1, -1, 0}, + {0, 1, 1}, + {0, 1, -1}, + {0, -1, 1}, + {0, -1, -1}, + // Share a corner: + {1, 1, 1}, + {1, -1, -1}, + {-1, 1, -1}, + {-1, -1, 1}, } for _, direction := range directions { From 4ede385e16a3650988725e6c2b0e468dfb8cca47 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 17:10:09 +0330 Subject: [PATCH 656/775] Fix: consider neighbors in same voxel --- render/finiteelements/buffer/disconnection_ele.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 53a29df73..42f7becfc 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -55,6 +55,8 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { // // You'll need to adjust: directions := [][3]int{ + // The same voxel. + {0, 0, 0}, // Share a face: {1, 0, 0}, {-1, 0, 0}, From e238545e4d2a359df69ea4803c05dca4bb9376b1 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 17:13:05 +0330 Subject: [PATCH 657/775] Fix: some neighbor directions were missing --- render/finiteelements/buffer/disconnection_ele.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 42f7becfc..86b237807 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -55,8 +55,6 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { // // You'll need to adjust: directions := [][3]int{ - // The same voxel. - {0, 0, 0}, // Share a face: {1, 0, 0}, {-1, 0, 0}, @@ -73,11 +71,21 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { {0, 1, -1}, {0, -1, 1}, {0, -1, -1}, + {1, 0, 1}, + {1, 0, -1}, + {-1, 0, 1}, + {-1, 0, -1}, // Share a corner: {1, 1, 1}, + {1, 1, -1}, + {1, -1, 1}, {1, -1, -1}, + {-1, 1, 1}, {-1, 1, -1}, {-1, -1, 1}, + {-1, -1, -1}, + // Center voxel itself: + {0, 0, 0}, } for _, direction := range directions { From 88a483f7c2ca45420f5a1bf698a2e62e900e48a2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 3 Aug 2023 17:16:09 +0330 Subject: [PATCH 658/775] Replace directions with loops --- .../buffer/disconnection_ele.go | 66 ++++--------------- 1 file changed, 14 insertions(+), 52 deletions(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 86b237807..ad67e505e 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -46,60 +46,22 @@ func (vg *VoxelGrid) BFS(visited map[*Element]bool, start *Element, v [3]int) { func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { var neighbors []*Element - // The 3D directions to iterate over. - // - // Two voxels could be considered neighbors if: - // 1) They share a face. - // 2) They share an edge. - // 3) They share a corner. - // - // You'll need to adjust: - directions := [][3]int{ - // Share a face: - {1, 0, 0}, - {-1, 0, 0}, - {0, 1, 0}, - {0, -1, 0}, - {0, 0, 1}, - {0, 0, -1}, - // Share an edge: - {1, 1, 0}, - {1, -1, 0}, - {-1, 1, 0}, - {-1, -1, 0}, - {0, 1, 1}, - {0, 1, -1}, - {0, -1, 1}, - {0, -1, -1}, - {1, 0, 1}, - {1, 0, -1}, - {-1, 0, 1}, - {-1, 0, -1}, - // Share a corner: - {1, 1, 1}, - {1, 1, -1}, - {1, -1, 1}, - {1, -1, -1}, - {-1, 1, 1}, - {-1, 1, -1}, - {-1, -1, 1}, - {-1, -1, -1}, - // Center voxel itself: - {0, 0, 0}, - } - - for _, direction := range directions { - x := v[0] + direction[0] - y := v[1] + direction[1] - z := v[2] + direction[2] + for i := -1; i <= 1; i++ { + for j := -1; j <= 1; j++ { + for k := -1; k <= 1; k++ { + x := v[0] + i + y := v[1] + j + z := v[2] + k - if !vg.isValid(x, y, z) { - continue - } + if !vg.isValid(x, y, z) { + continue + } - for _, el := range vg.Get(x, y, z) { - if sharesNode(e, el) { - neighbors = append(neighbors, el) + for _, el := range vg.Get(x, y, z) { + if sharesNode(e, el) { + neighbors = append(neighbors, el) + } + } } } } From 54af8752e920df0ae417389723fe2dafcb3ad059 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 5 Aug 2023 11:38:09 +0330 Subject: [PATCH 659/775] Fix: skip same element while computing neighbors --- render/finiteelements/buffer/disconnection_ele.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index ad67e505e..cccef5bb6 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -58,6 +58,12 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { } for _, el := range vg.Get(x, y, z) { + if i == 0 && j == 0 && k == 0 { + // The same voxel: skip the same element. + if el != e { + continue + } + } if sharesNode(e, el) { neighbors = append(neighbors, el) } From f94e73b5cbcae00048179ffb8454426c6c0b7d94 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 5 Aug 2023 12:43:56 +0330 Subject: [PATCH 660/775] The fix that smells like a hack. Change it later. https://github.com/deadsy/sdfx/pull/73#issuecomment-1652737493 --- examples/stl_to_sdf_evaluation/main.go | 26 +++++++++++ obj/stl.go | 61 ++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 examples/stl_to_sdf_evaluation/main.go diff --git a/examples/stl_to_sdf_evaluation/main.go b/examples/stl_to_sdf_evaluation/main.go new file mode 100644 index 000000000..87e0ad825 --- /dev/null +++ b/examples/stl_to_sdf_evaluation/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "log" + + "github.com/deadsy/sdfx/obj" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +func main() { + // create the SDF from the STL file mesh. + inSdf, err := obj.ImportSTL("../../files/teapot.stl", 20, 3, 5) + if err != nil { + log.Fatalf("error: %s", err) + } + + // This point is definitely inside the teapot model, + // so SDF value should be negative. + value := inSdf.Evaluate(v3.Vec{X: -0.8164382918936324, Y: 2.542909114087213, Z: 5.006102143191411}) + if value >= 0 { + fmt.Println("not expected") + } else { + fmt.Println("as expected") + } +} diff --git a/obj/stl.go b/obj/stl.go index 0dcc36e8a..1c8689303 100644 --- a/obj/stl.go +++ b/obj/stl.go @@ -39,6 +39,10 @@ func (t *triMeshSdf) Evaluate(p v3.Vec) float64 { closestTriangle := math.MaxFloat64 // Quickly skip checking most triangles by only checking the N closest neighbours (AABB based) neighbors := t.rtree.NearestNeighbors(t.numNeighbors, v3ToPoint(p)) + + // To check if all the distances have the same sign. + dists := make([]float64, 0, t.numNeighbors) + for _, neighbor := range neighbors { triangle := neighbor.(*sdf.Triangle3) testPointToTriangle := p.Sub(triangle[0]) @@ -50,10 +54,67 @@ func (t *triMeshSdf) Evaluate(p v3.Vec) float64 { closestTriangle = distToTri signedDistanceResult = signedDistanceToTriPlane } + dists = append(dists, signedDistanceToTriPlane) } + + // Does the approach of this paper make sense: + // https://www2.imm.dtu.dk/pubdb/edoc/imm1289.pdf + // TODO: If so, try to implement it in the future. + + if !sameSign(dists) { + // Sometimes the sign of the final result is not consistent. + signedDistanceResult = signConsistency(dists, signedDistanceResult) + } + return signedDistanceResult } +func sameSign(values []float64) bool { + + positive, negative := false, false + + for _, v := range values { + if v > 0 { + positive = true + } else if v < 0 { + negative = true + } + + // If we've seen both positive and negative, return early + if positive && negative { + return false + } + } + + // All values must have been the same sign + return true +} + +func signConsistency(values []float64, value float64) float64 { + positive := 0 + negative := 0 + + for _, v := range values { + if v > 0 { + positive++ + } else if v < 0 { + negative++ + } + } + + if positive > negative { + if value < 0 { + return -value + } + } else if negative > positive { + if value > 0 { + return -value + } + } + + return value +} + func (t *triMeshSdf) BoundingBox() sdf.Box3 { return t.bb } From 3da817935177713b2153d94110f5a0ed581196ca Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 5 Aug 2023 15:16:19 +0330 Subject: [PATCH 661/775] Fix bug: skip same element --- render/finiteelements/buffer/disconnection_ele.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index cccef5bb6..6844a4bc0 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -60,7 +60,7 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { for _, el := range vg.Get(x, y, z) { if i == 0 && j == 0 && k == 0 { // The same voxel: skip the same element. - if el != e { + if el == e { continue } } From 0439a338a9586dae803b1a149cec43209650a26b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 5 Aug 2023 15:45:58 +0330 Subject: [PATCH 662/775] Fix typo --- render/finiteelements/mesh/inp.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/render/finiteelements/mesh/inp.go b/render/finiteelements/mesh/inp.go index 51f34cf24..c5a79f360 100644 --- a/render/finiteelements/mesh/inp.go +++ b/render/finiteelements/mesh/inp.go @@ -278,7 +278,7 @@ func (inp *Inp) writeElements() error { return err } - _, err = fC3D10.WriteString(fmt.Sprintf("*ELEMENT, TYPE=%s, ELSET=e3D10\n", "C3D10")) + _, err = fC3D10.WriteString(fmt.Sprintf("*ELEMENT, TYPE=%s, ELSET=eC3D10\n", "C3D10")) if err != nil { return err } @@ -575,7 +575,7 @@ func (inp *Inp) writeFooter(f *os.File) error { } // Assign material to all elements - _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=e3D10\n") + _, err = f.WriteString("*SOLID SECTION,MATERIAL=resin,ELSET=eC3D10\n") if err != nil { return err } @@ -641,7 +641,7 @@ func (inp *Inp) writeFooter(f *os.File) error { } _, err = f.WriteString( fmt.Sprintf( - "e3D10,GRAV,%v,%v,%v,%v\n", + "eC3D10,GRAV,%v,%v,%v,%v\n", inp.GravityMagnitude, inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, ), From bf49b90b45b9fab998d8c70b3bd030d40b262c23 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 6 Aug 2023 12:12:37 +0330 Subject: [PATCH 663/775] Nested loop order: make it consistent --- render/finiteelements/buffer/disconnection_ele.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 6844a4bc0..7f325e1ef 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -6,9 +6,9 @@ func (vg *VoxelGrid) Components() int { // Map key is (x, y, z) index of voxel. visited := make(map[*Element]bool) count := 0 - for z := 0; z < vg.Len.Z; z++ { + for x := 0; x < vg.Len.X; x++ { for y := 0; y < vg.Len.Y; y++ { - for x := 0; x < vg.Len.X; x++ { + for z := 0; z < vg.Len.Z; z++ { els := vg.Get(x, y, z) for _, el := range els { if !visited[el] { From d146ea26149a5ed8fd4ef7286e3ad4c11d827620 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 6 Aug 2023 12:29:59 +0330 Subject: [PATCH 664/775] Fix bug: compute neighbors by correct voxel --- .../finiteelements/buffer/disconnection_ele.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 7f325e1ef..62c3be17e 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -23,28 +23,35 @@ func (vg *VoxelGrid) Components() int { } // Algorithm: breadth-first search (BFS). -func (vg *VoxelGrid) BFS(visited map[*Element]bool, start *Element, v [3]int) { +func (vg *VoxelGrid) BFS(visited map[*Element]bool, start *Element, startV [3]int) { queue := []*Element{start} + quVox := [][3]int{startV} // To store the voxel of each element. visited[start] = true for len(queue) > 0 { e := queue[0] + v := quVox[0] queue = queue[1:] + quVox = quVox[1:] - neighbors := vg.neighbors(e, v) + neighbors, neighVoxs := vg.neighbors(e, v) - for _, n := range neighbors { + for i := range neighbors { + n := neighbors[i] + nv := neighVoxs[i] if !visited[n] { visited[n] = true queue = append(queue, n) + quVox = append(quVox, nv) } } } } // It returns a list of neighbors. -func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { +func (vg *VoxelGrid) neighbors(e *Element, v [3]int) ([]*Element, [][3]int) { var neighbors []*Element + var neighVoxs [][3]int for i := -1; i <= 1; i++ { for j := -1; j <= 1; j++ { @@ -66,13 +73,14 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) []*Element { } if sharesNode(e, el) { neighbors = append(neighbors, el) + neighVoxs = append(neighVoxs, [3]int{x, y, z}) } } } } } - return neighbors + return neighbors, neighVoxs } func sharesNode(e1, e2 *Element) bool { From 27f6553b8328d0e0675436c643c1f04f60d9d5c5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 6 Aug 2023 16:41:33 +0330 Subject: [PATCH 665/775] Fix bug: node count can be different for neighbors --- render/finiteelements/buffer/disconnection_ele.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go index 62c3be17e..206c31fcb 100644 --- a/render/finiteelements/buffer/disconnection_ele.go +++ b/render/finiteelements/buffer/disconnection_ele.go @@ -84,9 +84,9 @@ func (vg *VoxelGrid) neighbors(e *Element, v [3]int) ([]*Element, [][3]int) { } func sharesNode(e1, e2 *Element) bool { - if len(e1.Nodes) != len(e2.Nodes) { - return false - } + // The node count doesn't need to be equal for the two elements. + // Since, the two elements could be of different types. + for _, n1 := range e1.Nodes { if contains(e2.Nodes, n1) { return true From 69e9f5de0dac93d52431819544f3d6ea5201ee7f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 11:48:08 +0330 Subject: [PATCH 666/775] Rename func --- examples/finite_elements/main.go | 4 ++-- render/finiteelements/mesh/fem.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 5bfdf233e..56a63a816 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -218,7 +218,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) - components := m.CountComponents() + components := m.Components() fmt.Printf("components count: %v\n", components) // Write all layers of mesh to file. @@ -235,7 +235,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape ) error { // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) - components := m.CountComponents() + components := m.Components() fmt.Printf("components count: %v\n", components) // Write just some layers of mesh to file. diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 44a6cb7f7..105612fc2 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -133,7 +133,7 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. -func (m *Fem) CountComponents() int { +func (m *Fem) Components() int { return m.IBuff.Grid.Components() } From c7034e452e3c9270ec1945b6f3e837254dec1222 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 11:57:19 +0330 Subject: [PATCH 667/775] Rename func --- render/finiteelements/buffer/disconnection.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 7038926c4..5a8e22fb1 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -1,7 +1,7 @@ package buffer // Count separate components consisting of disconnected voxels. -func (vg *VoxelGrid) VoxelComponents() int { +func (vg *VoxelGrid) ComponentsByVoxel() int { // Map key is (x, y, z) index of voxel. visited := make(map[[3]int]bool) count := 0 From bbe2c74d01241f51d5eef93abbb26f879cb1f127 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 11:59:30 +0330 Subject: [PATCH 668/775] Rename files --- render/finiteelements/buffer/disconnection.go | 112 +++++++++++------- .../buffer/disconnection_ele.go | 107 ----------------- .../buffer/disconnection_voxel.go | 81 +++++++++++++ 3 files changed, 150 insertions(+), 150 deletions(-) delete mode 100644 render/finiteelements/buffer/disconnection_ele.go create mode 100644 render/finiteelements/buffer/disconnection_voxel.go diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 5a8e22fb1..55ea5351a 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -1,17 +1,20 @@ package buffer -// Count separate components consisting of disconnected voxels. -func (vg *VoxelGrid) ComponentsByVoxel() int { +// Count separate components consisting of disconnected finite elements. +// They cause FEA solver to throw error. +func (vg *VoxelGrid) Components() int { // Map key is (x, y, z) index of voxel. - visited := make(map[[3]int]bool) + visited := make(map[*Element]bool) count := 0 - for z := 0; z < vg.Len.Z; z++ { + for x := 0; x < vg.Len.X; x++ { for y := 0; y < vg.Len.Y; y++ { - for x := 0; x < vg.Len.X; x++ { - // If voxel is not empty and if it's not already visited. - if len(vg.Get(x, y, z)) > 0 && !visited[[3]int{x, y, z}] { - count++ - vg.bfs(visited, [3]int{x, y, z}) + for z := 0; z < vg.Len.Z; z++ { + els := vg.Get(x, y, z) + for _, el := range els { + if !visited[el] { + count++ + vg.bfs(visited, el, [3]int{x, y, z}) + } } } } @@ -19,63 +22,86 @@ func (vg *VoxelGrid) ComponentsByVoxel() int { return count } -// Algorithm: breadth-first search (BFS). -func (vg *VoxelGrid) bfs(visited map[[3]int]bool, start [3]int) { - queue := [][3]int{start} +// Algorithm: breadth-first search (bfs). +func (vg *VoxelGrid) bfs(visited map[*Element]bool, start *Element, startV [3]int) { + queue := []*Element{start} + quVox := [][3]int{startV} // To store the voxel of each element. visited[start] = true for len(queue) > 0 { - v := queue[0] + e := queue[0] + v := quVox[0] queue = queue[1:] + quVox = quVox[1:] - neighbors := vg.nonemptyNeighbors(v) + neighbors, neighVoxs := vg.neighbors(e, v) - for _, n := range neighbors { + for i := range neighbors { + n := neighbors[i] + nv := neighVoxs[i] if !visited[n] { visited[n] = true queue = append(queue, n) + quVox = append(quVox, nv) } } } } -// It returns a list of neighbor voxels that are non-empty. -func (vg *VoxelGrid) nonemptyNeighbors(v [3]int) [][3]int { - var neighbors [][3]int +// It returns a list of neighbors. +func (vg *VoxelGrid) neighbors(e *Element, v [3]int) ([]*Element, [][3]int) { + var neighbors []*Element + var neighVoxs [][3]int - // The 3D directions to iterate over. - // Two voxels are considered neighbors if they share a face, - // i.e., they are adjacent along x, y, or z direction. - directions := [][3]int{ - {1, 0, 0}, - {-1, 0, 0}, - {0, 1, 0}, - {0, -1, 0}, - {0, 0, 1}, - {0, 0, -1}, - } + for i := -1; i <= 1; i++ { + for j := -1; j <= 1; j++ { + for k := -1; k <= 1; k++ { + x := v[0] + i + y := v[1] + j + z := v[2] + k - for _, direction := range directions { - x := v[0] + direction[0] - y := v[1] + direction[1] - z := v[2] + direction[2] + if !vg.isValid(x, y, z) { + continue + } - if !vg.isValid(x, y, z) { - continue + for _, el := range vg.Get(x, y, z) { + if i == 0 && j == 0 && k == 0 { + // The same voxel: skip the same element. + if el == e { + continue + } + } + if sharesNode(e, el) { + neighbors = append(neighbors, el) + neighVoxs = append(neighVoxs, [3]int{x, y, z}) + } + } + } } + } - // Is neighbor voxel non-empty? - if len(vg.Get(x, y, z)) > 0 { - neighbors = append(neighbors, [3]int{x, y, z}) + return neighbors, neighVoxs +} + +func sharesNode(e1, e2 *Element) bool { + // The node count doesn't need to be equal for the two elements. + // Since, the two elements could be of different types. + + for _, n1 := range e1.Nodes { + if contains(e2.Nodes, n1) { + return true } } - - return neighbors + return false } -// Is voxel index inside a valid range? -func (vg *VoxelGrid) isValid(x, y, z int) bool { - return x >= 0 && y >= 0 && z >= 0 && x < vg.Len.X && y < vg.Len.Y && z < vg.Len.Z +func contains(arr []uint32, i uint32) bool { + for _, n := range arr { + if n == i { + return true + } + } + return false } //----------------------------------------------------------------------------- diff --git a/render/finiteelements/buffer/disconnection_ele.go b/render/finiteelements/buffer/disconnection_ele.go deleted file mode 100644 index 206c31fcb..000000000 --- a/render/finiteelements/buffer/disconnection_ele.go +++ /dev/null @@ -1,107 +0,0 @@ -package buffer - -// Count separate components consisting of disconnected finite elements. -// They cause FEA solver to throw error. -func (vg *VoxelGrid) Components() int { - // Map key is (x, y, z) index of voxel. - visited := make(map[*Element]bool) - count := 0 - for x := 0; x < vg.Len.X; x++ { - for y := 0; y < vg.Len.Y; y++ { - for z := 0; z < vg.Len.Z; z++ { - els := vg.Get(x, y, z) - for _, el := range els { - if !visited[el] { - count++ - vg.BFS(visited, el, [3]int{x, y, z}) - } - } - } - } - } - return count -} - -// Algorithm: breadth-first search (BFS). -func (vg *VoxelGrid) BFS(visited map[*Element]bool, start *Element, startV [3]int) { - queue := []*Element{start} - quVox := [][3]int{startV} // To store the voxel of each element. - visited[start] = true - - for len(queue) > 0 { - e := queue[0] - v := quVox[0] - queue = queue[1:] - quVox = quVox[1:] - - neighbors, neighVoxs := vg.neighbors(e, v) - - for i := range neighbors { - n := neighbors[i] - nv := neighVoxs[i] - if !visited[n] { - visited[n] = true - queue = append(queue, n) - quVox = append(quVox, nv) - } - } - } -} - -// It returns a list of neighbors. -func (vg *VoxelGrid) neighbors(e *Element, v [3]int) ([]*Element, [][3]int) { - var neighbors []*Element - var neighVoxs [][3]int - - for i := -1; i <= 1; i++ { - for j := -1; j <= 1; j++ { - for k := -1; k <= 1; k++ { - x := v[0] + i - y := v[1] + j - z := v[2] + k - - if !vg.isValid(x, y, z) { - continue - } - - for _, el := range vg.Get(x, y, z) { - if i == 0 && j == 0 && k == 0 { - // The same voxel: skip the same element. - if el == e { - continue - } - } - if sharesNode(e, el) { - neighbors = append(neighbors, el) - neighVoxs = append(neighVoxs, [3]int{x, y, z}) - } - } - } - } - } - - return neighbors, neighVoxs -} - -func sharesNode(e1, e2 *Element) bool { - // The node count doesn't need to be equal for the two elements. - // Since, the two elements could be of different types. - - for _, n1 := range e1.Nodes { - if contains(e2.Nodes, n1) { - return true - } - } - return false -} - -func contains(arr []uint32, i uint32) bool { - for _, n := range arr { - if n == i { - return true - } - } - return false -} - -//----------------------------------------------------------------------------- diff --git a/render/finiteelements/buffer/disconnection_voxel.go b/render/finiteelements/buffer/disconnection_voxel.go new file mode 100644 index 000000000..60482b3ab --- /dev/null +++ b/render/finiteelements/buffer/disconnection_voxel.go @@ -0,0 +1,81 @@ +package buffer + +// Count separate components consisting of disconnected voxels. +func (vg *VoxelGrid) ComponentsByVoxel() int { + // Map key is (x, y, z) index of voxel. + visited := make(map[[3]int]bool) + count := 0 + for z := 0; z < vg.Len.Z; z++ { + for y := 0; y < vg.Len.Y; y++ { + for x := 0; x < vg.Len.X; x++ { + // If voxel is not empty and if it's not already visited. + if len(vg.Get(x, y, z)) > 0 && !visited[[3]int{x, y, z}] { + count++ + vg.bfsByVoxel(visited, [3]int{x, y, z}) + } + } + } + } + return count +} + +// Algorithm: breadth-first search (BFS). +func (vg *VoxelGrid) bfsByVoxel(visited map[[3]int]bool, start [3]int) { + queue := [][3]int{start} + visited[start] = true + + for len(queue) > 0 { + v := queue[0] + queue = queue[1:] + + neighbors := vg.nonemptyNeighbors(v) + + for _, n := range neighbors { + if !visited[n] { + visited[n] = true + queue = append(queue, n) + } + } + } +} + +// It returns a list of neighbor voxels that are non-empty. +func (vg *VoxelGrid) nonemptyNeighbors(v [3]int) [][3]int { + var neighbors [][3]int + + // The 3D directions to iterate over. + // Two voxels are considered neighbors if they share a face, + // i.e., they are adjacent along x, y, or z direction. + directions := [][3]int{ + {1, 0, 0}, + {-1, 0, 0}, + {0, 1, 0}, + {0, -1, 0}, + {0, 0, 1}, + {0, 0, -1}, + } + + for _, direction := range directions { + x := v[0] + direction[0] + y := v[1] + direction[1] + z := v[2] + direction[2] + + if !vg.isValid(x, y, z) { + continue + } + + // Is neighbor voxel non-empty? + if len(vg.Get(x, y, z)) > 0 { + neighbors = append(neighbors, [3]int{x, y, z}) + } + } + + return neighbors +} + +// Is voxel index inside a valid range? +func (vg *VoxelGrid) isValid(x, y, z int) bool { + return x >= 0 && y >= 0 && z >= 0 && x < vg.Len.X && y < vg.Len.Y && z < vg.Len.Z +} + +//----------------------------------------------------------------------------- From b08ad6015db4913b6bb29ca2ce1ec00afc9682a7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 12:01:04 +0330 Subject: [PATCH 669/775] Move func --- render/finiteelements/buffer/disconnection.go | 7 +++++++ render/finiteelements/buffer/disconnection_voxel.go | 5 ----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 55ea5351a..2697167b3 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -105,3 +105,10 @@ func contains(arr []uint32, i uint32) bool { } //----------------------------------------------------------------------------- + +// Is voxel index inside a valid range? +func (vg *VoxelGrid) isValid(x, y, z int) bool { + return x >= 0 && y >= 0 && z >= 0 && x < vg.Len.X && y < vg.Len.Y && z < vg.Len.Z +} + +//----------------------------------------------------------------------------- diff --git a/render/finiteelements/buffer/disconnection_voxel.go b/render/finiteelements/buffer/disconnection_voxel.go index 60482b3ab..9273b0cd1 100644 --- a/render/finiteelements/buffer/disconnection_voxel.go +++ b/render/finiteelements/buffer/disconnection_voxel.go @@ -73,9 +73,4 @@ func (vg *VoxelGrid) nonemptyNeighbors(v [3]int) [][3]int { return neighbors } -// Is voxel index inside a valid range? -func (vg *VoxelGrid) isValid(x, y, z int) bool { - return x >= 0 && y >= 0 && z >= 0 && x < vg.Len.X && y < vg.Len.Y && z < vg.Len.Z -} - //----------------------------------------------------------------------------- From 5c6c94a1ed1b2a9ee2c6b591a3f08eb369317913 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 12:25:21 +0330 Subject: [PATCH 670/775] Iterate by a method --- render/finiteelements/buffer/disconnection.go | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 2697167b3..5cdb83f16 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -3,22 +3,17 @@ package buffer // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. func (vg *VoxelGrid) Components() int { - // Map key is (x, y, z) index of voxel. visited := make(map[*Element]bool) count := 0 - for x := 0; x < vg.Len.X; x++ { - for y := 0; y < vg.Len.Y; y++ { - for z := 0; z < vg.Len.Z; z++ { - els := vg.Get(x, y, z) - for _, el := range els { - if !visited[el] { - count++ - vg.bfs(visited, el, [3]int{x, y, z}) - } - } + process := func(x, y, z int, els []*Element) { + for _, el := range els { + if !visited[el] { + count++ + vg.bfs(visited, el, [3]int{x, y, z}) } } } + vg.Iterate(process) return count } From 6b7927253b03988c654edbe7877d57a2340c4f9d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 12:29:16 +0330 Subject: [PATCH 671/775] Iterate by a method --- .../finiteelements/buffer/disconnection_voxel.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/render/finiteelements/buffer/disconnection_voxel.go b/render/finiteelements/buffer/disconnection_voxel.go index 9273b0cd1..ccdb029c1 100644 --- a/render/finiteelements/buffer/disconnection_voxel.go +++ b/render/finiteelements/buffer/disconnection_voxel.go @@ -5,17 +5,14 @@ func (vg *VoxelGrid) ComponentsByVoxel() int { // Map key is (x, y, z) index of voxel. visited := make(map[[3]int]bool) count := 0 - for z := 0; z < vg.Len.Z; z++ { - for y := 0; y < vg.Len.Y; y++ { - for x := 0; x < vg.Len.X; x++ { - // If voxel is not empty and if it's not already visited. - if len(vg.Get(x, y, z)) > 0 && !visited[[3]int{x, y, z}] { - count++ - vg.bfsByVoxel(visited, [3]int{x, y, z}) - } - } + process := func(x, y, z int, els []*Element) { + // If voxel is not empty and if it's not already visited. + if len(els) > 0 && !visited[[3]int{x, y, z}] { + count++ + vg.bfsByVoxel(visited, [3]int{x, y, z}) } } + vg.Iterate(process) return count } From ec7dccd9253ad6a86d7cf6cd9d310469a2085e9f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 16:24:18 +0330 Subject: [PATCH 672/775] Component info --- examples/finite_elements/main.go | 10 +++++-- render/finiteelements/buffer/disconnection.go | 30 +++++++++++++++---- render/finiteelements/buffer/indexbuffer.go | 5 ++++ render/finiteelements/buffer/voxel.go | 6 ++++ render/finiteelements/mesh/fem.go | 2 +- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 56a63a816..3b0347f7f 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -219,7 +219,10 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) components := m.Components() - fmt.Printf("components count: %v\n", components) + fmt.Printf("components count: %v\n", len(components)) + for i, component := range components { + fmt.Printf("component %v voxel count: %v\n", i, len(component.Voxels)) + } // Write all layers of mesh to file. return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) @@ -236,7 +239,10 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape // Create a mesh out of finite elements. m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) components := m.Components() - fmt.Printf("components count: %v\n", components) + fmt.Printf("components count: %v\n", len(components)) + for i, component := range components { + fmt.Printf("component %v voxel count: %v\n", i, len(component.Voxels)) + } // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/disconnection.go index 5cdb83f16..580e1b7c5 100644 --- a/render/finiteelements/buffer/disconnection.go +++ b/render/finiteelements/buffer/disconnection.go @@ -1,28 +1,42 @@ package buffer +// Component represents a set of connected elements. +type Component struct { + Voxels map[[3]int]struct{} // A map avoids repeated voxels. +} + +func (c *Component) VoxelCount() int { + return len(c.Voxels) +} + // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. -func (vg *VoxelGrid) Components() int { +func (vg *VoxelGrid) Components() []*Component { visited := make(map[*Element]bool) - count := 0 + components := make([]*Component, 0) process := func(x, y, z int, els []*Element) { for _, el := range els { if !visited[el] { - count++ - vg.bfs(visited, el, [3]int{x, y, z}) + component := vg.bfs(visited, el, [3]int{x, y, z}) + components = append(components, component) } } } vg.Iterate(process) - return count + return components } // Algorithm: breadth-first search (bfs). -func (vg *VoxelGrid) bfs(visited map[*Element]bool, start *Element, startV [3]int) { +func (vg *VoxelGrid) bfs(visited map[*Element]bool, start *Element, startV [3]int) *Component { queue := []*Element{start} quVox := [][3]int{startV} // To store the voxel of each element. visited[start] = true + component := &Component{ + Voxels: make(map[[3]int]struct{}, 0), + } + component.Voxels[startV] = struct{}{} + for len(queue) > 0 { e := queue[0] v := quVox[0] @@ -38,9 +52,13 @@ func (vg *VoxelGrid) bfs(visited map[*Element]bool, start *Element, startV [3]in visited[n] = true queue = append(queue, n) quVox = append(quVox, nv) + + component.Voxels[nv] = struct{}{} } } } + + return component } // It returns a list of neighbors. diff --git a/render/finiteelements/buffer/indexbuffer.go b/render/finiteelements/buffer/indexbuffer.go index 8eb48de7e..d38e712ea 100644 --- a/render/finiteelements/buffer/indexbuffer.go +++ b/render/finiteelements/buffer/indexbuffer.go @@ -26,6 +26,11 @@ func (ib *IB) AddFE(x, y, z int, nodes []uint32) { ib.Grid.Append(x, y, z, NewElement(nodes)) } +// To delete all elements off of a voxel. +func (ib *IB) DelAll(x, y, z int) { + ib.Grid.DelAll(x, y, z) +} + // To iterate over all voxels and get elements inside each voxel and do stuff with them. func (ib *IB) Iterate(f func(int, int, int, []*Element)) { ib.Grid.Iterate(f) diff --git a/render/finiteelements/buffer/voxel.go b/render/finiteelements/buffer/voxel.go index 35cf1d174..3fe9d5094 100644 --- a/render/finiteelements/buffer/voxel.go +++ b/render/finiteelements/buffer/voxel.go @@ -112,6 +112,12 @@ func (vg *VoxelGrid) Append(x, y, z int, value *Element) { vg.Voxels[vg.index3Dto1D(x, y, z)].data = append(vg.Voxels[vg.index3Dto1D(x, y, z)].data, value) } +// To delete all elements off of a voxel. +func (vg *VoxelGrid) DelAll(x, y, z int) { + vg.Voxels[vg.index3Dto1D(x, y, z)].data = nil + vg.Voxels[vg.index3Dto1D(x, y, z)].data = make([]*Element, 0) +} + // Compute the bounding box of all the input points. // Return all the voxels that are intersecting with that bounding box. func (vg *VoxelGrid) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 105612fc2..3d9b672a1 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -133,7 +133,7 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. -func (m *Fem) Components() int { +func (m *Fem) Components() []*buffer.Component { return m.IBuff.Grid.Components() } From 17b66d8237a0a3599449cd6b8c07636d8e66f8bd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 16:25:19 +0330 Subject: [PATCH 673/775] Rename file --- render/finiteelements/buffer/{disconnection.go => component.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename render/finiteelements/buffer/{disconnection.go => component.go} (100%) diff --git a/render/finiteelements/buffer/disconnection.go b/render/finiteelements/buffer/component.go similarity index 100% rename from render/finiteelements/buffer/disconnection.go rename to render/finiteelements/buffer/component.go From 02190d478bcefbabccf3ea6a33ef2fca9f32de0e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 16:29:16 +0330 Subject: [PATCH 674/775] Call a method rather than using `len` --- examples/finite_elements/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 3b0347f7f..506a90d24 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -221,7 +221,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth components := m.Components() fmt.Printf("components count: %v\n", len(components)) for i, component := range components { - fmt.Printf("component %v voxel count: %v\n", i, len(component.Voxels)) + fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } // Write all layers of mesh to file. @@ -241,7 +241,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape components := m.Components() fmt.Printf("components count: %v\n", len(components)) for i, component := range components { - fmt.Printf("component %v voxel count: %v\n", i, len(component.Voxels)) + fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } // Write just some layers of mesh to file. From 147277c629713045ea4668c967a91072fdf0f24b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 16:34:18 +0330 Subject: [PATCH 675/775] Delete file --- .../buffer/disconnection_voxel.go | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 render/finiteelements/buffer/disconnection_voxel.go diff --git a/render/finiteelements/buffer/disconnection_voxel.go b/render/finiteelements/buffer/disconnection_voxel.go deleted file mode 100644 index ccdb029c1..000000000 --- a/render/finiteelements/buffer/disconnection_voxel.go +++ /dev/null @@ -1,73 +0,0 @@ -package buffer - -// Count separate components consisting of disconnected voxels. -func (vg *VoxelGrid) ComponentsByVoxel() int { - // Map key is (x, y, z) index of voxel. - visited := make(map[[3]int]bool) - count := 0 - process := func(x, y, z int, els []*Element) { - // If voxel is not empty and if it's not already visited. - if len(els) > 0 && !visited[[3]int{x, y, z}] { - count++ - vg.bfsByVoxel(visited, [3]int{x, y, z}) - } - } - vg.Iterate(process) - return count -} - -// Algorithm: breadth-first search (BFS). -func (vg *VoxelGrid) bfsByVoxel(visited map[[3]int]bool, start [3]int) { - queue := [][3]int{start} - visited[start] = true - - for len(queue) > 0 { - v := queue[0] - queue = queue[1:] - - neighbors := vg.nonemptyNeighbors(v) - - for _, n := range neighbors { - if !visited[n] { - visited[n] = true - queue = append(queue, n) - } - } - } -} - -// It returns a list of neighbor voxels that are non-empty. -func (vg *VoxelGrid) nonemptyNeighbors(v [3]int) [][3]int { - var neighbors [][3]int - - // The 3D directions to iterate over. - // Two voxels are considered neighbors if they share a face, - // i.e., they are adjacent along x, y, or z direction. - directions := [][3]int{ - {1, 0, 0}, - {-1, 0, 0}, - {0, 1, 0}, - {0, -1, 0}, - {0, 0, 1}, - {0, 0, -1}, - } - - for _, direction := range directions { - x := v[0] + direction[0] - y := v[1] + direction[1] - z := v[2] + direction[2] - - if !vg.isValid(x, y, z) { - continue - } - - // Is neighbor voxel non-empty? - if len(vg.Get(x, y, z)) > 0 { - neighbors = append(neighbors, [3]int{x, y, z}) - } - } - - return neighbors -} - -//----------------------------------------------------------------------------- From 48606daa90155cdfbdbc8dd0a0133533ecc69902 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 16:48:53 +0330 Subject: [PATCH 676/775] Clean disconnected components from largest one: Why? For our application, disconnected components may usually mean small details. And we know that small details are not needed: > ... STL (and other CAD) models often contain lots of small details that are irrelevant for the analysis, but force the use of lots of small elements. > ... (omitting small and inconsequential details) in my experience tends to produce a higher quality mesh, shorter calculation times and better results. https://calculix.discourse.group/t/filter-bad-finite-elements/1689/5?u=megidd --- examples/finite_elements/main.go | 2 ++ render/finiteelements/buffer/clean.go | 31 +++++++++++++++++++++++++++ render/finiteelements/mesh/fem.go | 4 ++++ 3 files changed, 37 insertions(+) create mode 100644 render/finiteelements/buffer/clean.go diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 506a90d24..9d085b1ed 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -223,6 +223,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth for i, component := range components { fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } + m.CleanDisconnections(components) // Write all layers of mesh to file. return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) @@ -243,6 +244,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape for i, component := range components { fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } + m.CleanDisconnections(components) // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) diff --git a/render/finiteelements/buffer/clean.go b/render/finiteelements/buffer/clean.go new file mode 100644 index 000000000..b59a6cb5e --- /dev/null +++ b/render/finiteelements/buffer/clean.go @@ -0,0 +1,31 @@ +package buffer + +import "fmt" + +// Rather than connecting disconnected components, we can keep the largest one and delete the rest. +func (vg *VoxelGrid) CleanDisconnections(components []*Component) { + // Find largest component. Consider volume criterion. + maxComponentIndex := -1 + maxVoxelCount := 0 + for i, component := range components { + if component.VoxelCount() > maxVoxelCount { + maxVoxelCount = component.VoxelCount() + maxComponentIndex = i + } + } + + if maxComponentIndex != -1 { + fmt.Printf("Component %v has the largest voxel count: %v\n", maxComponentIndex, maxVoxelCount) + } else { + fmt.Printf("No components found.") + } + + // Remove elements inside the voxels of smaller components. + for i, component := range components { + if i != maxComponentIndex { + for v := range component.Voxels { + vg.DelAll(v[0], v[1], v[2]) + } + } + } +} diff --git a/render/finiteelements/mesh/fem.go b/render/finiteelements/mesh/fem.go index 3d9b672a1..92515e7b2 100644 --- a/render/finiteelements/mesh/fem.go +++ b/render/finiteelements/mesh/fem.go @@ -137,6 +137,10 @@ func (m *Fem) Components() []*buffer.Component { return m.IBuff.Grid.Components() } +func (m *Fem) CleanDisconnections(components []*buffer.Component) { + m.IBuff.Grid.CleanDisconnections(components) +} + //----------------------------------------------------------------------------- // WriteInp writes mesh to ABAQUS or CalculiX `inp` file. From 283d8a1a4c22a934fd0b3fbecf97a7f3df42f99e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 16:58:28 +0330 Subject: [PATCH 677/775] Log component count after clean up --- examples/finite_elements/main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 9d085b1ed..3a3040ae3 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -224,6 +224,8 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } m.CleanDisconnections(components) + components = m.Components() + fmt.Printf("components count after clean up: %v\n", len(components)) // Write all layers of mesh to file. return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) @@ -245,6 +247,8 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } m.CleanDisconnections(components) + components = m.Components() + fmt.Printf("components count after clean up: %v\n", len(components)) // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) From 2f9282e04b7a708beef7102e58a88fdc40598e5b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 8 Aug 2023 17:01:48 +0330 Subject: [PATCH 678/775] Return if no component is found --- render/finiteelements/buffer/clean.go | 1 + 1 file changed, 1 insertion(+) diff --git a/render/finiteelements/buffer/clean.go b/render/finiteelements/buffer/clean.go index b59a6cb5e..65d6eeb74 100644 --- a/render/finiteelements/buffer/clean.go +++ b/render/finiteelements/buffer/clean.go @@ -18,6 +18,7 @@ func (vg *VoxelGrid) CleanDisconnections(components []*Component) { fmt.Printf("Component %v has the largest voxel count: %v\n", maxComponentIndex, maxVoxelCount) } else { fmt.Printf("No components found.") + return } // Remove elements inside the voxels of smaller components. From 0402742c7b22ec849310b20c5cf72cad10f38a8e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 10 Aug 2023 10:19:17 +0330 Subject: [PATCH 679/775] Test linear elements: https://calculix.discourse.group/t/connection-of-hex-and-tet-elements/1755/22?u=megidd --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 3a3040ae3..961dd4556 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -47,7 +47,7 @@ const ( // Written file can be used by ABAQUS or CalculiX. func main() { benchmark := Square - elementconfig := Hex20Tet10 + elementconfig := Hex8Tet4 // Optional argument from 1 to 4 to specify the benchmark to run. if len(os.Args) > 1 { From 4d6201958969bfb47052c5257c5b1fb11cacf881 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 10 Aug 2023 10:21:09 +0330 Subject: [PATCH 680/775] No cleanup of smaller components --- examples/finite_elements/main.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 961dd4556..e049d5708 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -223,9 +223,6 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth for i, component := range components { fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } - m.CleanDisconnections(components) - components = m.Components() - fmt.Printf("components count after clean up: %v\n", len(components)) // Write all layers of mesh to file. return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) @@ -246,9 +243,6 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape for i, component := range components { fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } - m.CleanDisconnections(components) - components = m.Components() - fmt.Printf("components count after clean up: %v\n", len(components)) // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) From 8e02c2588f8f78e095c0654baec89248d3f573e8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Thu, 10 Aug 2023 10:27:56 +0330 Subject: [PATCH 681/775] Tet4: use nodes at cube edge middle --- render/marchfelogic.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/marchfelogic.go b/render/marchfelogic.go index 6c09a72fa..37734c4b2 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -241,7 +241,7 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) if mcEdgeTable[index]&bit != 0 { a := mcPairTable[i][0] b := mcPairTable[i][1] - points[i] = mcInterpolate(p[a], p[b], v[a], v[b], x) + points[i] = mcInterpolateFE(p[a], p[b], v[a], v[b], x) } } From 0a8296de7e96a43163a05ede6ebc945ebfe2f674 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 12 Aug 2023 17:03:13 +0330 Subject: [PATCH 682/775] Apply upstream optimization and refactor: * Move finite element to `sdf` pkg. * Use buffering of finite elements: * This results in fewer channel writes and removes channel performance as a bottleneck. --- examples/finite_elements/main.go | 2 +- render/fe.go | 41 -------- render/marchfe.go | 4 +- render/marchfelogic.go | 35 +++---- render/render.go | 12 +-- sdf/fe.go | 97 +++++++++++++++++++ .../finiteelements/buffer/buffer.go | 0 .../finiteelements/buffer/clean.go | 0 .../finiteelements/buffer/component.go | 0 .../finiteelements/buffer/indexbuffer.go | 0 .../finiteelements/buffer/vertexbuffer.go | 0 .../finiteelements/buffer/voxel.go | 0 {render => sdf}/finiteelements/mesh/fem.go | 2 +- {render => sdf}/finiteelements/mesh/inp.go | 2 +- {render => sdf}/finiteelements/mesh/mesh.go | 0 .../finiteelements/mesh/restraint_load.go | 0 16 files changed, 124 insertions(+), 71 deletions(-) delete mode 100644 render/fe.go create mode 100644 sdf/fe.go rename {render => sdf}/finiteelements/buffer/buffer.go (100%) rename {render => sdf}/finiteelements/buffer/clean.go (100%) rename {render => sdf}/finiteelements/buffer/component.go (100%) rename {render => sdf}/finiteelements/buffer/indexbuffer.go (100%) rename {render => sdf}/finiteelements/buffer/vertexbuffer.go (100%) rename {render => sdf}/finiteelements/buffer/voxel.go (100%) rename {render => sdf}/finiteelements/mesh/fem.go (98%) rename {render => sdf}/finiteelements/mesh/inp.go (99%) rename {render => sdf}/finiteelements/mesh/mesh.go (100%) rename {render => sdf}/finiteelements/mesh/restraint_load.go (100%) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index e049d5708..a8f011c14 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -17,8 +17,8 @@ import ( "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" - "github.com/deadsy/sdfx/render/finiteelements/mesh" "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/sdf/finiteelements/mesh" v3 "github.com/deadsy/sdfx/vec/v3" ) diff --git a/render/fe.go b/render/fe.go deleted file mode 100644 index a401fd897..000000000 --- a/render/fe.go +++ /dev/null @@ -1,41 +0,0 @@ -package render - -import ( - "sync" - - v3 "github.com/deadsy/sdfx/vec/v3" -) - -// Fe is a finite element. -type Fe struct { - // Coordinates of nodes or vertices. - V []v3.Vec - // Coordinates of the voxel to which the element belongs. - X int - Y int - Z int -} - -//----------------------------------------------------------------------------- - -// writeFe writes a stream of finite elements to an array. -func writeFe(wg *sync.WaitGroup, elements *[]Fe) chan<- []*Fe { - // External code writes to this channel. - // This goroutine reads the channel and stores finite elements. - c := make(chan []*Fe) - - wg.Add(1) - go func() { - defer wg.Done() - // read finite elements from the channel and handle them - for fes := range c { - for _, fe := range fes { - *elements = append(*elements, *fe) - } - } - }() - - return c -} - -//----------------------------------------------------------------------------- diff --git a/render/marchfe.go b/render/marchfe.go index d314ffeb0..605a7b9da 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -61,7 +61,7 @@ func (r *MarchingCubesFEUniform) Info(s sdf.SDF3) string { // Render produces a finite elements mesh over the bounding volume of an sdf3. // Order and shape of finite elements are selectable. -func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output chan<- []*Fe) { +func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output sdf.FeWriter) { // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() @@ -70,7 +70,7 @@ func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output chan<- []*Fe) { bb1Size = bb1Size.Ceil().AddScalar(1) bb1Size = bb1Size.MulScalar(meshInc) bb := sdf.NewBox3(bb0.Center(), bb1Size) - output <- marchingCubesFE(s, bb, meshInc, r.order, r.shape) + marchingCubesFE(s, bb, meshInc, r.order, r.shape, output) } //----------------------------------------------------------------------------- diff --git a/render/marchfelogic.go b/render/marchfelogic.go index 37734c4b2..3bf85a781 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -6,8 +6,7 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape Shape) []*Fe { - var fes []*Fe +func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape Shape, output sdf.FeWriter) { size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) @@ -54,21 +53,19 @@ func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape l.Get(1, y, z+1), l.Get(1, y+1, z+1), l.Get(0, y+1, z+1)} - fes = append(fes, mcToFE(corners, values, x, y, z, order, shape)...) + output.Write(mcToFE(corners, values, x, y, z, order, shape)) p.Z += dz } p.Y += dy } p.X += dx } - - return fes } //----------------------------------------------------------------------------- -func mcToFE(corners [8]v3.Vec, values [8]float64, x, y, z int, order Order, shape Shape) []*Fe { - var fes []*Fe +func mcToFE(corners [8]v3.Vec, values [8]float64, x, y, z int, order Order, shape Shape) []*sdf.Fe { + var fes []*sdf.Fe switch order { case Linear: { @@ -125,8 +122,8 @@ func mcToFE(corners [8]v3.Vec, values [8]float64, x, y, z int, order Order, shap //----------------------------------------------------------------------------- -func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { - result := make([]*Fe, 0) +func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*sdf.Fe { + result := make([]*sdf.Fe, 0) anyPositive := false for i := 0; i < 8; i++ { @@ -140,7 +137,7 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) // Finite element is inside the 3D model if all values are non-positive. if !anyPositive { - fe := Fe{ + fe := sdf.Fe{ V: make([]v3.Vec, 8), X: layerX, Y: layerY, @@ -166,8 +163,8 @@ func mcToHex8(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) //----------------------------------------------------------------------------- -func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { - result := make([]*Fe, 0) +func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*sdf.Fe { + result := make([]*sdf.Fe, 0) anyPositive := false for i := 0; i < 8; i++ { @@ -181,7 +178,7 @@ func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) // Finite element is inside the 3D model if all values are non-positive. if !anyPositive { - fe := Fe{ + fe := sdf.Fe{ V: make([]v3.Vec, 20), X: layerX, Y: layerY, @@ -225,7 +222,7 @@ func mcToHex20(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) //----------------------------------------------------------------------------- -func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { +func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*sdf.Fe { // which of the 0..255 patterns do we have? index := 0 for i := 0; i < 8; i++ { @@ -248,9 +245,9 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) // Create the tetrahedra. table := mcTetrahedronTable[index] count := len(table) / 4 - result := make([]*Fe, 0, count) + result := make([]*sdf.Fe, 0, count) for i := 0; i < count; i++ { - t := Fe{ + t := sdf.Fe{ V: make([]v3.Vec, 4), X: layerX, Y: layerY, @@ -280,7 +277,7 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) //----------------------------------------------------------------------------- -func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*Fe { +func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) []*sdf.Fe { // which of the 0..255 patterns do we have? index := 0 for i := 0; i < 8; i++ { @@ -303,9 +300,9 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) // Create the tetrahedra. table := mcTetrahedronTable[index] count := len(table) / 4 - result := make([]*Fe, 0, count) + result := make([]*sdf.Fe, 0, count) for i := 0; i < count; i++ { - t := Fe{ + t := sdf.Fe{ V: make([]v3.Vec, 10), X: layerX, Y: layerY, diff --git a/render/render.go b/render/render.go index c68dbd1f9..f131b0934 100644 --- a/render/render.go +++ b/render/render.go @@ -33,7 +33,7 @@ type Render2 interface { // RenderFE renders a finite element mesh over the bounding volume of an sdf3. type RenderFE interface { - RenderFE(sdf3 sdf.SDF3, output chan<- []*Fe) + RenderFE(sdf3 sdf.SDF3, output sdf.FeWriter) Info(sdf3 sdf.SDF3) string Voxels(sdf3 sdf.SDF3) (v3i.Vec, v3.Vec, []v3.Vec, []v3.Vec) } @@ -65,22 +65,22 @@ func ToTriangles( func ToFem( s sdf.SDF3, // sdf3 to render r RenderFE, // rendering method -) []Fe { +) []sdf.Fe { fmt.Printf("rendering %s\n", r.Info(s)) voxelCount, _, _, _ := r.Voxels(s) fmt.Printf("voxel counts of marching algorithm are: (%v x %v x %v)\n", voxelCount.X, voxelCount.Y, voxelCount.Z) // Will be filled by the rendering. - fes := make([]Fe, 0) + fes := make([]sdf.Fe, 0) var wg sync.WaitGroup - // Get the channel to be written to. - output := writeFe(&wg, &fes) + // To write the finite elements. + output := sdf.WriteFes(&wg, &fes) // run the renderer - r.RenderFE(s, output) + r.RenderFE(s, sdf.NewFeBuffer(output)) // stop the writer reading on the channel close(output) // wait for the file write to complete diff --git a/sdf/fe.go b/sdf/fe.go new file mode 100644 index 000000000..9da5463d6 --- /dev/null +++ b/sdf/fe.go @@ -0,0 +1,97 @@ +package sdf + +import ( + "sync" + + v3 "github.com/deadsy/sdfx/vec/v3" +) + +// Fe is a finite element. +type Fe struct { + // Coordinates of nodes or vertices. + V []v3.Vec + // Coordinates of the voxel to which the element belongs. + X int + Y int + Z int +} + +//----------------------------------------------------------------------------- + +// WriteFes writes a stream of finite elements to a slice. +func WriteFes(wg *sync.WaitGroup, elements *[]Fe) chan<- []*Fe { + // External code writes to this channel. + // This goroutine reads the channel and stores finite elements. + c := make(chan []*Fe) + + wg.Add(1) + go func() { + defer wg.Done() + // read finite elements from the channel and handle them + for fes := range c { + for _, fe := range fes { + *elements = append(*elements, *fe) + } + } + }() + + return c +} + +//----------------------------------------------------------------------------- +// Finite element Buffering + +// We write finite elements to a channel to decouple the rendering routines from the +// routine that writes file output. We have a lot of finite elements and channels +// are not very fast, so it's best to bundle many finite elements into a single channel +// write. The renderer doesn't naturally do that, so we buffer finite elements before +// writing them to the channel. + +// FeWriter is the interface of a finite element writer/closer object. +type FeWriter interface { + Write(in []*Fe) error + Close() error +} + +// size the buffer to avoid re-allocations when appending. +const feBufferSize = 256 +const feBufferMargin = 8 // marching cubes produces 0 to 6 finite elements + +// FeBuffer buffers finite elements before writing them to a channel. +type FeBuffer struct { + buf []*Fe // finite element buffer + out chan<- []*Fe // output channel + lock sync.Mutex // lock the the buffer during access +} + +// NewFeBuffer returns a FeBuffer. +func NewFeBuffer(out chan<- []*Fe) FeWriter { + return &FeBuffer{ + buf: make([]*Fe, 0, feBufferSize+feBufferMargin), + out: out, + } +} + +func (a *FeBuffer) Write(in []*Fe) error { + a.lock.Lock() + a.buf = append(a.buf, in...) + if len(a.buf) >= tBufferSize { + a.out <- a.buf + a.buf = make([]*Fe, 0, feBufferSize+feBufferMargin) + } + a.lock.Unlock() + return nil +} + +// Close flushes out any remaining finite elements in the buffer. +func (a *FeBuffer) Close() error { + a.lock.Lock() + if len(a.buf) != 0 { + a.out <- a.buf + a.buf = nil + } + a.lock.Unlock() + return nil +} + +//----------------------------------------------------------------------------- diff --git a/render/finiteelements/buffer/buffer.go b/sdf/finiteelements/buffer/buffer.go similarity index 100% rename from render/finiteelements/buffer/buffer.go rename to sdf/finiteelements/buffer/buffer.go diff --git a/render/finiteelements/buffer/clean.go b/sdf/finiteelements/buffer/clean.go similarity index 100% rename from render/finiteelements/buffer/clean.go rename to sdf/finiteelements/buffer/clean.go diff --git a/render/finiteelements/buffer/component.go b/sdf/finiteelements/buffer/component.go similarity index 100% rename from render/finiteelements/buffer/component.go rename to sdf/finiteelements/buffer/component.go diff --git a/render/finiteelements/buffer/indexbuffer.go b/sdf/finiteelements/buffer/indexbuffer.go similarity index 100% rename from render/finiteelements/buffer/indexbuffer.go rename to sdf/finiteelements/buffer/indexbuffer.go diff --git a/render/finiteelements/buffer/vertexbuffer.go b/sdf/finiteelements/buffer/vertexbuffer.go similarity index 100% rename from render/finiteelements/buffer/vertexbuffer.go rename to sdf/finiteelements/buffer/vertexbuffer.go diff --git a/render/finiteelements/buffer/voxel.go b/sdf/finiteelements/buffer/voxel.go similarity index 100% rename from render/finiteelements/buffer/voxel.go rename to sdf/finiteelements/buffer/voxel.go diff --git a/render/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go similarity index 98% rename from render/finiteelements/mesh/fem.go rename to sdf/finiteelements/mesh/fem.go index 92515e7b2..21958de65 100644 --- a/render/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -4,8 +4,8 @@ import ( "math" "github.com/deadsy/sdfx/render" - "github.com/deadsy/sdfx/render/finiteelements/buffer" "github.com/deadsy/sdfx/sdf" + "github.com/deadsy/sdfx/sdf/finiteelements/buffer" v3 "github.com/deadsy/sdfx/vec/v3" "github.com/deadsy/sdfx/vec/v3i" ) diff --git a/render/finiteelements/mesh/inp.go b/sdf/finiteelements/mesh/inp.go similarity index 99% rename from render/finiteelements/mesh/inp.go rename to sdf/finiteelements/mesh/inp.go index c5a79f360..93b60eab6 100644 --- a/render/finiteelements/mesh/inp.go +++ b/sdf/finiteelements/mesh/inp.go @@ -5,7 +5,7 @@ import ( "os" "time" - "github.com/deadsy/sdfx/render/finiteelements/buffer" + "github.com/deadsy/sdfx/sdf/finiteelements/buffer" v3 "github.com/deadsy/sdfx/vec/v3" ) diff --git a/render/finiteelements/mesh/mesh.go b/sdf/finiteelements/mesh/mesh.go similarity index 100% rename from render/finiteelements/mesh/mesh.go rename to sdf/finiteelements/mesh/mesh.go diff --git a/render/finiteelements/mesh/restraint_load.go b/sdf/finiteelements/mesh/restraint_load.go similarity index 100% rename from render/finiteelements/mesh/restraint_load.go rename to sdf/finiteelements/mesh/restraint_load.go From f1b5ad4ed0c4428cc9ba5937e4402126b927aa3a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 12 Aug 2023 17:25:03 +0330 Subject: [PATCH 683/775] Rename --- examples/finite_elements/main.go | 8 ++++---- render/marchfe.go | 2 +- render/marchfelogic.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index a8f011c14..06fd8d700 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -180,12 +180,12 @@ func benchmarkRun( } case Hex8Tet4: { - err = fe(inSdf, resolution, render.Linear, render.Both, "hex8tet4.inp", restraints, loads) + err = fe(inSdf, resolution, render.Linear, render.HexAndTet, "hex8tet4.inp", restraints, loads) if err != nil { log.Fatalf("error: %s", err) } - err = feLayers(inSdf, resolution, render.Linear, render.Both, + err = feLayers(inSdf, resolution, render.Linear, render.HexAndTet, fmt.Sprintf("hex8tet4--layers-%v-to-%v.inp", layerStart, layerEnd), restraints, loads, layerStart, layerEnd, ) @@ -195,12 +195,12 @@ func benchmarkRun( } case Hex20Tet10: { - err = fe(inSdf, resolution, render.Quadratic, render.Both, "hex20tet10.inp", restraints, loads) + err = fe(inSdf, resolution, render.Quadratic, render.HexAndTet, "hex20tet10.inp", restraints, loads) if err != nil { log.Fatalf("error: %s", err) } - err = feLayers(inSdf, resolution, render.Quadratic, render.Both, + err = feLayers(inSdf, resolution, render.Quadratic, render.HexAndTet, fmt.Sprintf("hex20tet10--layers-%v-to-%v.inp", layerStart, layerEnd), restraints, loads, layerStart, layerEnd, ) diff --git a/render/marchfe.go b/render/marchfe.go index 605a7b9da..b4c1dc66a 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -27,7 +27,7 @@ type Shape int const ( Hexahedral Shape = iota + 1 Tetrahedral - Both + HexAndTet ) //----------------------------------------------------------------------------- diff --git a/render/marchfelogic.go b/render/marchfelogic.go index 3bf85a781..90a7484ee 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -78,7 +78,7 @@ func mcToFE(corners [8]v3.Vec, values [8]float64, x, y, z int, order Order, shap { fes = append(fes, mcToTet4(corners, values, 0, x, y, z)...) } - case Both: + case HexAndTet: { // If all cube corners are inside surface mesh, a single hexahedral element is generated. // If all cube corners are outside surface mesh, no element is generated. @@ -102,7 +102,7 @@ func mcToFE(corners [8]v3.Vec, values [8]float64, x, y, z int, order Order, shap { fes = append(fes, mcToTet10(corners, values, 0, x, y, z)...) } - case Both: + case HexAndTet: { // If all cube corners are inside surface mesh, a single hexahedral element is generated. // If all cube corners are outside surface mesh, no element is generated. From 70c5e179420b867c728fcd517afa1992cdf79a93 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 12 Aug 2023 17:30:05 +0330 Subject: [PATCH 684/775] Rename --- examples/finite_elements/main.go | 4 ++-- render/marchfe.go | 18 +++++++++--------- render/marchfelogic.go | 2 +- render/render.go | 10 +++++----- sdf/finiteelements/mesh/fem.go | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 06fd8d700..5fbc541ee 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -217,7 +217,7 @@ func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth loads []*mesh.Load, ) error { // Create a mesh out of finite elements. - m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) + m, _ := mesh.NewFem(s, render.NewMarchingCubesFeUniform(resolution, order, shape)) components := m.Components() fmt.Printf("components count: %v\n", len(components)) for i, component := range components { @@ -237,7 +237,7 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape layerStart, layerEnd int, ) error { // Create a mesh out of finite elements. - m, _ := mesh.NewFem(s, render.NewMarchingCubesFEUniform(resolution, order, shape)) + m, _ := mesh.NewFem(s, render.NewMarchingCubesFeUniform(resolution, order, shape)) components := m.Components() fmt.Printf("components count: %v\n", len(components)) for i, component := range components { diff --git a/render/marchfe.go b/render/marchfe.go index b4c1dc66a..87671a162 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -32,16 +32,16 @@ const ( //----------------------------------------------------------------------------- -// MarchingCubesFEUniform renders using marching cubes with uniform space sampling. -type MarchingCubesFEUniform struct { +// MarchingCubesFeUniform renders using marching cubes with uniform space sampling. +type MarchingCubesFeUniform struct { meshCells int // number of cells on the longest axis of bounding box. e.g 200 order Order // Linear or quadratic. shape Shape // Hexahedral, tetrahedral, or both. } -// NewMarchingCubesFEUniform returns a RenderHex8 object. -func NewMarchingCubesFEUniform(meshCells int, order Order, shape Shape) *MarchingCubesFEUniform { - return &MarchingCubesFEUniform{ +// NewMarchingCubesFeUniform returns a RenderHex8 object. +func NewMarchingCubesFeUniform(meshCells int, order Order, shape Shape) *MarchingCubesFeUniform { + return &MarchingCubesFeUniform{ meshCells: meshCells, order: order, shape: shape, @@ -49,7 +49,7 @@ func NewMarchingCubesFEUniform(meshCells int, order Order, shape Shape) *Marchin } // Info returns a string describing the rendered volume. -func (r *MarchingCubesFEUniform) Info(s sdf.SDF3) string { +func (r *MarchingCubesFeUniform) Info(s sdf.SDF3) string { bb0 := s.BoundingBox() bb0Size := bb0.Size() meshInc := bb0Size.MaxComponent() / float64(r.meshCells) @@ -61,7 +61,7 @@ func (r *MarchingCubesFEUniform) Info(s sdf.SDF3) string { // Render produces a finite elements mesh over the bounding volume of an sdf3. // Order and shape of finite elements are selectable. -func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output sdf.FeWriter) { +func (r *MarchingCubesFeUniform) RenderFe(s sdf.SDF3, output sdf.FeWriter) { // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() @@ -70,14 +70,14 @@ func (r *MarchingCubesFEUniform) RenderFE(s sdf.SDF3, output sdf.FeWriter) { bb1Size = bb1Size.Ceil().AddScalar(1) bb1Size = bb1Size.MulScalar(meshInc) bb := sdf.NewBox3(bb0.Center(), bb1Size) - marchingCubesFE(s, bb, meshInc, r.order, r.shape, output) + marchingCubesFe(s, bb, meshInc, r.order, r.shape, output) } //----------------------------------------------------------------------------- // To get the voxel count, dimension, and min/max corner which are consistent with loops of marching algorithm. // This func loops are exactly like `marchingCubesFE` loops. We have to be consistant. -func (r *MarchingCubesFEUniform) Voxels(s sdf.SDF3) (v3i.Vec, v3.Vec, []v3.Vec, []v3.Vec) { +func (r *MarchingCubesFeUniform) Voxels(s sdf.SDF3) (v3i.Vec, v3.Vec, []v3.Vec, []v3.Vec) { // work out the region we will sample bb0 := s.BoundingBox() bb0Size := bb0.Size() diff --git a/render/marchfelogic.go b/render/marchfelogic.go index 90a7484ee..e54e53843 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -6,7 +6,7 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -func marchingCubesFE(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape Shape, output sdf.FeWriter) { +func marchingCubesFe(s sdf.SDF3, box sdf.Box3, step float64, order Order, shape Shape, output sdf.FeWriter) { size := box.Size() base := box.Min steps := conv.V3ToV3i(size.DivScalar(step).Ceil()) diff --git a/render/render.go b/render/render.go index f131b0934..26fec443c 100644 --- a/render/render.go +++ b/render/render.go @@ -31,9 +31,9 @@ type Render2 interface { Info(s sdf.SDF2) string } -// RenderFE renders a finite element mesh over the bounding volume of an sdf3. -type RenderFE interface { - RenderFE(sdf3 sdf.SDF3, output sdf.FeWriter) +// RenderFe renders a finite element mesh over the bounding volume of an sdf3. +type RenderFe interface { + RenderFe(sdf3 sdf.SDF3, output sdf.FeWriter) Info(sdf3 sdf.SDF3) string Voxels(sdf3 sdf.SDF3) (v3i.Vec, v3.Vec, []v3.Vec, []v3.Vec) } @@ -64,7 +64,7 @@ func ToTriangles( // ToFem renders an SDF3 to finite elements in the shape of 4-node tetrahedra. func ToFem( s sdf.SDF3, // sdf3 to render - r RenderFE, // rendering method + r RenderFe, // rendering method ) []sdf.Fe { fmt.Printf("rendering %s\n", r.Info(s)) @@ -80,7 +80,7 @@ func ToFem( output := sdf.WriteFes(&wg, &fes) // run the renderer - r.RenderFE(s, sdf.NewFeBuffer(output)) + r.RenderFe(s, sdf.NewFeBuffer(output)) // stop the writer reading on the channel close(output) // wait for the file write to complete diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 21958de65..4f4cabc2d 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -22,7 +22,7 @@ type Fem struct { } // NewFem returns a new mesh and number of its layers along Z-axis. -func NewFem(s sdf.SDF3, r render.RenderFE) (*Fem, int) { +func NewFem(s sdf.SDF3, r render.RenderFe) (*Fem, int) { fes := render.ToFem(s, r) voxelLen, voxelDim, mins, maxs := r.Voxels(s) From 1847e970394d77df506d9c1f0cc907901b2849b0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 12 Aug 2023 17:31:04 +0330 Subject: [PATCH 685/775] Fix comment --- render/marchfe.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/marchfe.go b/render/marchfe.go index 87671a162..889ed61a3 100644 --- a/render/marchfe.go +++ b/render/marchfe.go @@ -76,7 +76,7 @@ func (r *MarchingCubesFeUniform) RenderFe(s sdf.SDF3, output sdf.FeWriter) { //----------------------------------------------------------------------------- // To get the voxel count, dimension, and min/max corner which are consistent with loops of marching algorithm. -// This func loops are exactly like `marchingCubesFE` loops. We have to be consistant. +// This func loops are exactly like `marchingCubesFe` loops. We have to be consistant. func (r *MarchingCubesFeUniform) Voxels(s sdf.SDF3) (v3i.Vec, v3.Vec, []v3.Vec, []v3.Vec) { // work out the region we will sample bb0 := s.BoundingBox() From 9ab15749f2656226fdbd63e7f21982f44dd0a06d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 12 Aug 2023 17:35:18 +0330 Subject: [PATCH 686/775] Fix comment --- render/render.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/render.go b/render/render.go index 26fec443c..6b159959b 100644 --- a/render/render.go +++ b/render/render.go @@ -61,7 +61,7 @@ func ToTriangles( //----------------------------------------------------------------------------- -// ToFem renders an SDF3 to finite elements in the shape of 4-node tetrahedra. +// ToFem renders an SDF3 to finite elements. func ToFem( s sdf.SDF3, // sdf3 to render r RenderFe, // rendering method From c41c61e1415eef337ee0be0906b60ced5ad59ace Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 12 Aug 2023 17:41:06 +0330 Subject: [PATCH 687/775] TODO --- sdf/fe.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdf/fe.go b/sdf/fe.go index 9da5463d6..3d7ff8ef6 100644 --- a/sdf/fe.go +++ b/sdf/fe.go @@ -55,7 +55,9 @@ type FeWriter interface { // size the buffer to avoid re-allocations when appending. const feBufferSize = 256 -const feBufferMargin = 8 // marching cubes produces 0 to 6 finite elements + +// TODO: can value be further calibrated? +const feBufferMargin = 20 // marching cubes produces 0 to less than 20 finite elements. Depending upon element type. // FeBuffer buffers finite elements before writing them to a channel. type FeBuffer struct { From 6058f65f8eb5f366bde593854891dbd2ed96282d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 12 Aug 2023 17:44:11 +0330 Subject: [PATCH 688/775] TODO & comment --- sdf/fe.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdf/fe.go b/sdf/fe.go index 3d7ff8ef6..51f43cc1b 100644 --- a/sdf/fe.go +++ b/sdf/fe.go @@ -56,8 +56,10 @@ type FeWriter interface { // size the buffer to avoid re-allocations when appending. const feBufferSize = 256 +// marching cubes produces 0 or 1 finite element type of hex. +// marching cubes produces 0 to less than 20 finite element of type tet. // TODO: can value be further calibrated? -const feBufferMargin = 20 // marching cubes produces 0 to less than 20 finite elements. Depending upon element type. +const feBufferMargin = 20 // FeBuffer buffers finite elements before writing them to a channel. type FeBuffer struct { From b870aff0ff0d3adde38d2db0ba38a96a4dba6b98 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 12 Aug 2023 17:47:15 +0330 Subject: [PATCH 689/775] Comment --- sdf/fe.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdf/fe.go b/sdf/fe.go index 51f43cc1b..59b04bdad 100644 --- a/sdf/fe.go +++ b/sdf/fe.go @@ -58,6 +58,8 @@ const feBufferSize = 256 // marching cubes produces 0 or 1 finite element type of hex. // marching cubes produces 0 to less than 20 finite element of type tet. +// According to https://github.com/Megidd/tetrahedron-table +// // TODO: can value be further calibrated? const feBufferMargin = 20 From b92cb4fb1eed7c1f910200dcd367bf79357919c8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 28 Aug 2023 18:17:25 +0330 Subject: [PATCH 690/775] Test file --- examples/finite_elements/main_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 examples/finite_elements/main_test.go diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go new file mode 100644 index 000000000..5b10f126c --- /dev/null +++ b/examples/finite_elements/main_test.go @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- + +/* + +Finite elements from triangle mesh. +Output `inp` file is consumable by ABAQUS or CalculiX. + +*/ + +//----------------------------------------------------------------------------- + +package main + +import "testing" + +func Test_main(t *testing.T) { + tests := []struct { + name string + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + main() + }) + } +} From 6ea55625badebbf43ed0515f318576bb6a845331 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 13:12:39 +0330 Subject: [PATCH 691/775] JSON of specs --- examples/finite_elements/main_test.go | 253 +++++++++++++++++++++++++- 1 file changed, 250 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 5b10f126c..56a8ea2c6 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -11,13 +11,82 @@ Output `inp` file is consumable by ABAQUS or CalculiX. package main -import "testing" +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "testing" +) + +var bmsSpecsPth string = filepath.Join(os.TempDir(), "bms-specs.json") +var bmcSpecsPth string = filepath.Join(os.TempDir(), "bmc-specs.json") +var bmpSpecsPth string = filepath.Join(os.TempDir(), "bmp-specs.json") +var bmiSpecsPth string = filepath.Join(os.TempDir(), "bmi-specs.json") +var teapotSpecsPth string = filepath.Join(os.TempDir(), "teapot-specs.json") func Test_main(t *testing.T) { + setup() tests := []struct { - name string + skip bool + name string + pthStl string + pthSpecs string + pthLoadPoints string + pthLoadDirs string + pthLoadMags string + pthRestraints string }{ - // TODO: Add test cases. + { + skip: false, + name: "benchmarkSquare", + pthStl: "../../files/benchmark-square.stl", + pthSpecs: bmsSpecsPth, + pthLoadPoints: "", + pthLoadDirs: "", + pthLoadMags: "", + pthRestraints: "", + }, + { + skip: false, + name: "benchmarkCircle", + pthStl: "../../files/benchmark-circle.stl", + pthSpecs: bmcSpecsPth, + pthLoadPoints: "", + pthLoadDirs: "", + pthLoadMags: "", + pthRestraints: "", + }, + { + skip: false, + name: "benchmarkPipe", + pthStl: "../../files/benchmark-pipe.stl", + pthSpecs: bmpSpecsPth, + pthLoadPoints: "", + pthLoadDirs: "", + pthLoadMags: "", + pthRestraints: "", + }, + { + skip: false, + name: "benchmarkI", + pthStl: "../../files/benchmark-I.stl", + pthSpecs: bmiSpecsPth, + pthLoadPoints: "", + pthLoadDirs: "", + pthLoadMags: "", + pthRestraints: "", + }, + { + skip: false, + name: "teapot", + pthStl: "../../files/teapot.stl", + pthSpecs: teapotSpecsPth, + pthLoadPoints: "", + pthLoadDirs: "", + pthLoadMags: "", + pthRestraints: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -25,3 +94,181 @@ func Test_main(t *testing.T) { }) } } + +func setup() { + bmsSpecs() + bmcSpecs() + bmpSpecs() + bmiSpecs() + teapotSpecs() +} + +func bmsSpecs() { + specs := map[string]float64{ + "massDensity": 7.85e-9, + "youngModulus": 210000, + "poissonRatio": 0.3, + "gravityConsidered": 1, // 0 or 1 + "gravityDirectionX": 0, + "gravityDirectionY": 0, + "gravityDirectionZ": -1, + "gravityMagnitude": 9810, + "resolution": 50, + "layerStart": -1, // Negative means all layers. + "layerEnd": -1, // Negative means all layers. + "Tet4": 0, + "Tet10": 0, + "Hex8": 0, + "Hex20": 0, + "Hex8Tet4": 1, + "Hex20Tet10": 0, + } + + jsonData, err := json.MarshalIndent(specs, "", " ") + if err != nil { + fmt.Println("Failed to marshal JSON:", err) + return + } + + err = os.WriteFile(bmsSpecsPth, jsonData, 0644) + if err != nil { + fmt.Println("Failed to write JSON file:", err) + return + } +} + +func bmcSpecs() { + specs := map[string]float64{ + "massDensity": 7.85e-9, + "youngModulus": 210000, + "poissonRatio": 0.3, + "gravityConsidered": 1, // 0 or 1 + "gravityDirectionX": 0, + "gravityDirectionY": 0, + "gravityDirectionZ": -1, + "gravityMagnitude": 9810, + "resolution": 50, + "layerStart": -1, // Negative means all layers. + "layerEnd": -1, // Negative means all layers. + "Tet4": 0, + "Tet10": 0, + "Hex8": 0, + "Hex20": 0, + "Hex8Tet4": 1, + "Hex20Tet10": 0, + } + + jsonData, err := json.MarshalIndent(specs, "", " ") + if err != nil { + fmt.Println("Failed to marshal JSON:", err) + return + } + + err = os.WriteFile(bmcSpecsPth, jsonData, 0644) + if err != nil { + fmt.Println("Failed to write JSON file:", err) + return + } +} + +func bmpSpecs() { + specs := map[string]float64{ + "massDensity": 7.85e-9, + "youngModulus": 210000, + "poissonRatio": 0.3, + "gravityConsidered": 1, // 0 or 1 + "gravityDirectionX": 0, + "gravityDirectionY": 0, + "gravityDirectionZ": -1, + "gravityMagnitude": 9810, + "resolution": 50, + "layerStart": -1, // Negative means all layers. + "layerEnd": -1, // Negative means all layers. + "Tet4": 0, + "Tet10": 0, + "Hex8": 0, + "Hex20": 0, + "Hex8Tet4": 1, + "Hex20Tet10": 0, + } + + jsonData, err := json.MarshalIndent(specs, "", " ") + if err != nil { + fmt.Println("Failed to marshal JSON:", err) + return + } + + err = os.WriteFile(bmpSpecsPth, jsonData, 0644) + if err != nil { + fmt.Println("Failed to write JSON file:", err) + return + } +} + +func bmiSpecs() { + specs := map[string]float64{ + "massDensity": 7.85e-9, + "youngModulus": 210000, + "poissonRatio": 0.3, + "gravityConsidered": 1, // 0 or 1 + "gravityDirectionX": 0, + "gravityDirectionY": 0, + "gravityDirectionZ": -1, + "gravityMagnitude": 9810, + "resolution": 50, + "layerStart": -1, // Negative means all layers. + "layerEnd": -1, // Negative means all layers. + "Tet4": 0, + "Tet10": 0, + "Hex8": 0, + "Hex20": 0, + "Hex8Tet4": 1, + "Hex20Tet10": 0, + } + + jsonData, err := json.MarshalIndent(specs, "", " ") + if err != nil { + fmt.Println("Failed to marshal JSON:", err) + return + } + + err = os.WriteFile(bmiSpecsPth, jsonData, 0644) + if err != nil { + fmt.Println("Failed to write JSON file:", err) + return + } +} + +func teapotSpecs() { + specs := map[string]float64{ + "massDensity": 7.85e-9, + "youngModulus": 210000, + "poissonRatio": 0.3, + "gravityConsidered": 1, // 0 or 1 + "gravityDirectionX": 0, + "gravityDirectionY": 0, + "gravityDirectionZ": -1, + "gravityMagnitude": 9810, + "resolution": 50, + "layerStart": -1, // Negative means all layers. + "layerEnd": -1, // Negative means all layers. + "Tet4": 0, + "Tet10": 0, + "Hex8": 0, + "Hex20": 0, + "Hex8Tet4": 1, + "Hex20Tet10": 0, + } + + jsonData, err := json.MarshalIndent(specs, "", " ") + if err != nil { + fmt.Println("Failed to marshal JSON:", err) + return + } + + err = os.WriteFile(teapotSpecsPth, jsonData, 0644) + if err != nil { + fmt.Println("Failed to write JSON file:", err) + return + } +} From 33fa3c10e46f36f2fa8a0d7ba5b3c3b2d16723e3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 14:08:52 +0330 Subject: [PATCH 692/775] New type --- examples/finite_elements/main_test.go | 182 +++++++++++++------------- 1 file changed, 92 insertions(+), 90 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 56a8ea2c6..75544d337 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -103,25 +103,39 @@ func setup() { teapotSpecs() } +type Specs struct { + MassDensity float64 + YoungModulus float64 + PoissonRatio float64 + GravityConsidered bool + GravityDirectionX float64 + GravityDirectionY float64 + GravityDirectionZ float64 + GravityMagnitude float64 + Resolution int + LayersAllConsidered bool + LayerStart int + LayerEnd int + NonlinearConsidered bool + ExactSurfaceConsidered bool +} + func bmsSpecs() { - specs := map[string]float64{ - "massDensity": 7.85e-9, - "youngModulus": 210000, - "poissonRatio": 0.3, - "gravityConsidered": 1, // 0 or 1 - "gravityDirectionX": 0, - "gravityDirectionY": 0, - "gravityDirectionZ": -1, - "gravityMagnitude": 9810, - "resolution": 50, - "layerStart": -1, // Negative means all layers. - "layerEnd": -1, // Negative means all layers. - "Tet4": 0, - "Tet10": 0, - "Hex8": 0, - "Hex20": 0, - "Hex8Tet4": 1, - "Hex20Tet10": 0, + specs := Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityConsidered: true, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, } jsonData, err := json.MarshalIndent(specs, "", " ") @@ -138,24 +152,21 @@ func bmsSpecs() { } func bmcSpecs() { - specs := map[string]float64{ - "massDensity": 7.85e-9, - "youngModulus": 210000, - "poissonRatio": 0.3, - "gravityConsidered": 1, // 0 or 1 - "gravityDirectionX": 0, - "gravityDirectionY": 0, - "gravityDirectionZ": -1, - "gravityMagnitude": 9810, - "resolution": 50, - "layerStart": -1, // Negative means all layers. - "layerEnd": -1, // Negative means all layers. - "Tet4": 0, - "Tet10": 0, - "Hex8": 0, - "Hex20": 0, - "Hex8Tet4": 1, - "Hex20Tet10": 0, + specs := Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityConsidered: true, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, } jsonData, err := json.MarshalIndent(specs, "", " ") @@ -172,24 +183,21 @@ func bmcSpecs() { } func bmpSpecs() { - specs := map[string]float64{ - "massDensity": 7.85e-9, - "youngModulus": 210000, - "poissonRatio": 0.3, - "gravityConsidered": 1, // 0 or 1 - "gravityDirectionX": 0, - "gravityDirectionY": 0, - "gravityDirectionZ": -1, - "gravityMagnitude": 9810, - "resolution": 50, - "layerStart": -1, // Negative means all layers. - "layerEnd": -1, // Negative means all layers. - "Tet4": 0, - "Tet10": 0, - "Hex8": 0, - "Hex20": 0, - "Hex8Tet4": 1, - "Hex20Tet10": 0, + specs := Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityConsidered: true, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, } jsonData, err := json.MarshalIndent(specs, "", " ") @@ -206,24 +214,21 @@ func bmpSpecs() { } func bmiSpecs() { - specs := map[string]float64{ - "massDensity": 7.85e-9, - "youngModulus": 210000, - "poissonRatio": 0.3, - "gravityConsidered": 1, // 0 or 1 - "gravityDirectionX": 0, - "gravityDirectionY": 0, - "gravityDirectionZ": -1, - "gravityMagnitude": 9810, - "resolution": 50, - "layerStart": -1, // Negative means all layers. - "layerEnd": -1, // Negative means all layers. - "Tet4": 0, - "Tet10": 0, - "Hex8": 0, - "Hex20": 0, - "Hex8Tet4": 1, - "Hex20Tet10": 0, + specs := Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityConsidered: true, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, } jsonData, err := json.MarshalIndent(specs, "", " ") @@ -240,24 +245,21 @@ func bmiSpecs() { } func teapotSpecs() { - specs := map[string]float64{ - "massDensity": 7.85e-9, - "youngModulus": 210000, - "poissonRatio": 0.3, - "gravityConsidered": 1, // 0 or 1 - "gravityDirectionX": 0, - "gravityDirectionY": 0, - "gravityDirectionZ": -1, - "gravityMagnitude": 9810, - "resolution": 50, - "layerStart": -1, // Negative means all layers. - "layerEnd": -1, // Negative means all layers. - "Tet4": 0, - "Tet10": 0, - "Hex8": 0, - "Hex20": 0, - "Hex8Tet4": 1, - "Hex20Tet10": 0, + specs := Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityConsidered: true, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, } jsonData, err := json.MarshalIndent(specs, "", " ") From 103e92ba66107a39cc472ee0678a38223f815f24 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 14:16:48 +0330 Subject: [PATCH 693/775] Error handling --- examples/finite_elements/main_test.go | 87 ++++++++++++--------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 75544d337..7b5ba4219 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -13,7 +13,6 @@ package main import ( "encoding/json" - "fmt" "os" "path/filepath" "testing" @@ -26,7 +25,12 @@ var bmiSpecsPth string = filepath.Join(os.TempDir(), "bmi-specs.json") var teapotSpecsPth string = filepath.Join(os.TempDir(), "teapot-specs.json") func Test_main(t *testing.T) { - setup() + err := setup() + if err != nil { + t.Error(err) + return + } + tests := []struct { skip bool name string @@ -95,12 +99,24 @@ func Test_main(t *testing.T) { } } -func setup() { - bmsSpecs() - bmcSpecs() - bmpSpecs() - bmiSpecs() - teapotSpecs() +func setup() error { + err := bmsSpecs() + if err != nil { + return err + } + err = bmcSpecs() + if err != nil { + return err + } + err = bmpSpecs() + if err != nil { + return err + } + err = bmiSpecs() + if err != nil { + return err + } + return teapotSpecs() } type Specs struct { @@ -120,7 +136,7 @@ type Specs struct { ExactSurfaceConsidered bool } -func bmsSpecs() { +func bmsSpecs() error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -140,18 +156,13 @@ func bmsSpecs() { jsonData, err := json.MarshalIndent(specs, "", " ") if err != nil { - fmt.Println("Failed to marshal JSON:", err) - return + return err } - err = os.WriteFile(bmsSpecsPth, jsonData, 0644) - if err != nil { - fmt.Println("Failed to write JSON file:", err) - return - } + return os.WriteFile(bmsSpecsPth, jsonData, 0644) } -func bmcSpecs() { +func bmcSpecs() error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -171,18 +182,13 @@ func bmcSpecs() { jsonData, err := json.MarshalIndent(specs, "", " ") if err != nil { - fmt.Println("Failed to marshal JSON:", err) - return + return err } - err = os.WriteFile(bmcSpecsPth, jsonData, 0644) - if err != nil { - fmt.Println("Failed to write JSON file:", err) - return - } + return os.WriteFile(bmcSpecsPth, jsonData, 0644) } -func bmpSpecs() { +func bmpSpecs() error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -202,18 +208,13 @@ func bmpSpecs() { jsonData, err := json.MarshalIndent(specs, "", " ") if err != nil { - fmt.Println("Failed to marshal JSON:", err) - return + return err } - err = os.WriteFile(bmpSpecsPth, jsonData, 0644) - if err != nil { - fmt.Println("Failed to write JSON file:", err) - return - } + return os.WriteFile(bmpSpecsPth, jsonData, 0644) } -func bmiSpecs() { +func bmiSpecs() error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -233,18 +234,13 @@ func bmiSpecs() { jsonData, err := json.MarshalIndent(specs, "", " ") if err != nil { - fmt.Println("Failed to marshal JSON:", err) - return + return err } - err = os.WriteFile(bmiSpecsPth, jsonData, 0644) - if err != nil { - fmt.Println("Failed to write JSON file:", err) - return - } + return os.WriteFile(bmiSpecsPth, jsonData, 0644) } -func teapotSpecs() { +func teapotSpecs() error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -264,13 +260,8 @@ func teapotSpecs() { jsonData, err := json.MarshalIndent(specs, "", " ") if err != nil { - fmt.Println("Failed to marshal JSON:", err) - return + return err } - err = os.WriteFile(teapotSpecsPth, jsonData, 0644) - if err != nil { - fmt.Println("Failed to write JSON file:", err) - return - } + return os.WriteFile(teapotSpecsPth, jsonData, 0644) } From e779f27172e420e8308e88e5cdc60c7f1331e862 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 15:17:41 +0330 Subject: [PATCH 694/775] Restraints --- examples/finite_elements/main_test.go | 72 ++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 7b5ba4219..939377068 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -24,6 +24,12 @@ var bmpSpecsPth string = filepath.Join(os.TempDir(), "bmp-specs.json") var bmiSpecsPth string = filepath.Join(os.TempDir(), "bmi-specs.json") var teapotSpecsPth string = filepath.Join(os.TempDir(), "teapot-specs.json") +var bmsRestraintsPth string = filepath.Join(os.TempDir(), "bms-restraints.json") +var bmcRestraintsPth string = filepath.Join(os.TempDir(), "bmc-restraints.json") +var bmpRestraintsPth string = filepath.Join(os.TempDir(), "bmp-restraints.json") +var bmiRestraintsPth string = filepath.Join(os.TempDir(), "bmi-restraints.json") +var teapotRestraintsPth string = filepath.Join(os.TempDir(), "teapot-restraints.json") + func Test_main(t *testing.T) { err := setup() if err != nil { @@ -49,7 +55,7 @@ func Test_main(t *testing.T) { pthLoadPoints: "", pthLoadDirs: "", pthLoadMags: "", - pthRestraints: "", + pthRestraints: bmsRestraintsPth, }, { skip: false, @@ -59,7 +65,7 @@ func Test_main(t *testing.T) { pthLoadPoints: "", pthLoadDirs: "", pthLoadMags: "", - pthRestraints: "", + pthRestraints: bmcRestraintsPth, }, { skip: false, @@ -69,7 +75,7 @@ func Test_main(t *testing.T) { pthLoadPoints: "", pthLoadDirs: "", pthLoadMags: "", - pthRestraints: "", + pthRestraints: bmpRestraintsPth, }, { skip: false, @@ -79,7 +85,7 @@ func Test_main(t *testing.T) { pthLoadPoints: "", pthLoadDirs: "", pthLoadMags: "", - pthRestraints: "", + pthRestraints: bmiRestraintsPth, }, { skip: false, @@ -89,7 +95,7 @@ func Test_main(t *testing.T) { pthLoadPoints: "", pthLoadDirs: "", pthLoadMags: "", - pthRestraints: "", + pthRestraints: teapotRestraintsPth, }, } for _, tt := range tests { @@ -116,7 +122,12 @@ func setup() error { if err != nil { return err } - return teapotSpecs() + err = teapotSpecs() + if err != nil { + return err + } + err = bmsRestraints() + return err } type Specs struct { @@ -265,3 +276,52 @@ func teapotSpecs() error { return os.WriteFile(teapotSpecsPth, jsonData, 0644) } + +type Restraint struct { + LocationX float64 + LocationY float64 + LocationZ float64 + IsFixedX bool + IsFixedY bool + IsFixedZ bool +} + +func bmsRestraints() error { + restraints := make([]Restraint, 0) + + gap := 1.0 + var y float64 + for y <= 17.32 { + restraint := Restraint{ + LocationX: 0, + LocationY: y, + LocationZ: 0, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + } + restraints = append(restraints, restraint) + y += gap + } + + y = 0 + for y <= 17.32 { + restraint := Restraint{ + LocationX: 200, + LocationY: y, + LocationZ: 0, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, + } + restraints = append(restraints, restraint) + y += gap + } + + jsonData, err := json.MarshalIndent(restraints, "", " ") + if err != nil { + return err + } + + return os.WriteFile(bmsRestraintsPth, jsonData, 0644) +} From 4fadc7ec9e5cce0909f80f935b40e3fa988b152b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 15:41:13 +0330 Subject: [PATCH 695/775] Restraints for next test --- examples/finite_elements/main_test.go | 96 +++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 939377068..3a4b4a2b6 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -127,6 +127,10 @@ func setup() error { return err } err = bmsRestraints() + if err != nil { + return err + } + err = bmcRestraints() return err } @@ -325,3 +329,95 @@ func bmsRestraints() error { return os.WriteFile(bmsRestraintsPth, jsonData, 0644) } + +func bmcRestraints() error { + restraints := []Restraint{ + { + LocationX: 0, + LocationY: 0, + LocationZ: 0, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 0, + LocationY: -2.0313, + LocationZ: 0.213498, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 0, + LocationY: -3.97382, + LocationZ: 0.844661, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 0, + LocationY: 2.0313, + LocationZ: 0.213498, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 0, + LocationY: 3.97382, + LocationZ: 0.844661, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 200, + LocationY: 0, + LocationZ: 0, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 200, + LocationY: -2.0313, + LocationZ: 0.213498, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 200, + LocationY: -3.97382, + LocationZ: 0.844661, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 200, + LocationY: 2.0313, + LocationZ: 0.213498, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, + }, + { + LocationX: 200, + LocationY: 3.97382, + LocationZ: 0.844661, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, + }, + } + + jsonData, err := json.MarshalIndent(restraints, "", " ") + if err != nil { + return err + } + + return os.WriteFile(bmcRestraintsPth, jsonData, 0644) +} From 5309b557719aeb34896913c42d755aecd35edc5e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 15:46:53 +0330 Subject: [PATCH 696/775] Reformat --- examples/finite_elements/main_test.go | 126 ++++++-------------------- 1 file changed, 28 insertions(+), 98 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 3a4b4a2b6..6d374c120 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -282,12 +282,12 @@ func teapotSpecs() error { } type Restraint struct { - LocationX float64 - LocationY float64 - LocationZ float64 - IsFixedX bool - IsFixedY bool - IsFixedZ bool + LocX float64 + LocY float64 + LocZ float64 + IsFixedX bool + IsFixedY bool + IsFixedZ bool } func bmsRestraints() error { @@ -297,12 +297,12 @@ func bmsRestraints() error { var y float64 for y <= 17.32 { restraint := Restraint{ - LocationX: 0, - LocationY: y, - LocationZ: 0, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, + LocX: 0, + LocY: y, + LocZ: 0, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, } restraints = append(restraints, restraint) y += gap @@ -311,12 +311,12 @@ func bmsRestraints() error { y = 0 for y <= 17.32 { restraint := Restraint{ - LocationX: 200, - LocationY: y, - LocationZ: 0, - IsFixedX: false, - IsFixedY: true, - IsFixedZ: true, + LocX: 200, + LocY: y, + LocZ: 0, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, } restraints = append(restraints, restraint) y += gap @@ -332,86 +332,16 @@ func bmsRestraints() error { func bmcRestraints() error { restraints := []Restraint{ - { - LocationX: 0, - LocationY: 0, - LocationZ: 0, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 0, - LocationY: -2.0313, - LocationZ: 0.213498, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 0, - LocationY: -3.97382, - LocationZ: 0.844661, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 0, - LocationY: 2.0313, - LocationZ: 0.213498, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 0, - LocationY: 3.97382, - LocationZ: 0.844661, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 200, - LocationY: 0, - LocationZ: 0, - IsFixedX: false, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 200, - LocationY: -2.0313, - LocationZ: 0.213498, - IsFixedX: false, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 200, - LocationY: -3.97382, - LocationZ: 0.844661, - IsFixedX: false, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 200, - LocationY: 2.0313, - LocationZ: 0.213498, - IsFixedX: false, - IsFixedY: true, - IsFixedZ: true, - }, - { - LocationX: 200, - LocationY: 3.97382, - LocationZ: 0.844661, - IsFixedX: false, - IsFixedY: true, - IsFixedZ: true, - }, + {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, } jsonData, err := json.MarshalIndent(restraints, "", " ") From daebbbccfd1bb91708eba1a7704c94ed5f039db6 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 15:52:52 +0330 Subject: [PATCH 697/775] Restraints for next test --- examples/finite_elements/main_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 6d374c120..e2f5997fb 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -131,6 +131,10 @@ func setup() error { return err } err = bmcRestraints() + if err != nil { + return err + } + err = bmpRestraints() return err } @@ -351,3 +355,25 @@ func bmcRestraints() error { return os.WriteFile(bmcRestraintsPth, jsonData, 0644) } + +func bmpRestraints() error { + restraints := []Restraint{ + {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + } + + jsonData, err := json.MarshalIndent(restraints, "", " ") + if err != nil { + return err + } + + return os.WriteFile(bmpRestraintsPth, jsonData, 0644) +} From 8141898a2b99a76576f0b71a0b00ba7f6387970e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 15:57:32 +0330 Subject: [PATCH 698/775] Restraints for next test --- examples/finite_elements/main_test.go | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index e2f5997fb..4e1173e93 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -135,6 +135,10 @@ func setup() error { return err } err = bmpRestraints() + if err != nil { + return err + } + err = bmiRestraints() return err } @@ -377,3 +381,27 @@ func bmpRestraints() error { return os.WriteFile(bmpRestraintsPth, jsonData, 0644) } + +func bmiRestraints() error { + restraints := make([]Restraint, 0) + + gap := 1.0 + var y float64 + for y <= 25 { + restraints = append(restraints, Restraint{LocX: 0, LocY: y, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}) + y += gap + } + + y = 0 + for y <= 25 { + restraints = append(restraints, Restraint{LocX: 200, LocY: y, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}) + y += gap + } + + jsonData, err := json.MarshalIndent(restraints, "", " ") + if err != nil { + return err + } + + return os.WriteFile(bmiRestraintsPth, jsonData, 0644) +} From 7eb5fe0e41f800afd14da9a86a4e5bde21f55e11 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 16:04:12 +0330 Subject: [PATCH 699/775] Teapot restraints --- examples/finite_elements/main_test.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 4e1173e93..3dff41e96 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -139,7 +139,10 @@ func setup() error { return err } err = bmiRestraints() - return err + if err != nil { + return err + } + return teapotRestraints() } type Specs struct { @@ -405,3 +408,23 @@ func bmiRestraints() error { return os.WriteFile(bmiRestraintsPth, jsonData, 0644) } + +func teapotRestraints() error { + restraints := []Restraint{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + }, + } + + jsonData, err := json.MarshalIndent(restraints, "", " ") + if err != nil { + return err + } + + return os.WriteFile(teapotRestraintsPth, jsonData, 0644) +} From 2cb24124492b15ec72e94f7b9b8084fee97c9144 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 16:25:22 +0330 Subject: [PATCH 700/775] Loads JSON --- examples/finite_elements/main_test.go | 161 +++++++++++++++++++++++--- 1 file changed, 142 insertions(+), 19 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 3dff41e96..fefb45bea 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -24,6 +24,12 @@ var bmpSpecsPth string = filepath.Join(os.TempDir(), "bmp-specs.json") var bmiSpecsPth string = filepath.Join(os.TempDir(), "bmi-specs.json") var teapotSpecsPth string = filepath.Join(os.TempDir(), "teapot-specs.json") +var bmsLoadsPth string = filepath.Join(os.TempDir(), "bms-loads.json") +var bmcLoadsPth string = filepath.Join(os.TempDir(), "bmc-loads.json") +var bmpLoadsPth string = filepath.Join(os.TempDir(), "bmp-loads.json") +var bmiLoadsPth string = filepath.Join(os.TempDir(), "bmi-loads.json") +var teapotLoadsPth string = filepath.Join(os.TempDir(), "teapot-loads.json") + var bmsRestraintsPth string = filepath.Join(os.TempDir(), "bms-restraints.json") var bmcRestraintsPth string = filepath.Join(os.TempDir(), "bmc-restraints.json") var bmpRestraintsPth string = filepath.Join(os.TempDir(), "bmp-restraints.json") @@ -42,9 +48,7 @@ func Test_main(t *testing.T) { name string pthStl string pthSpecs string - pthLoadPoints string - pthLoadDirs string - pthLoadMags string + pthLoads string pthRestraints string }{ { @@ -52,9 +56,7 @@ func Test_main(t *testing.T) { name: "benchmarkSquare", pthStl: "../../files/benchmark-square.stl", pthSpecs: bmsSpecsPth, - pthLoadPoints: "", - pthLoadDirs: "", - pthLoadMags: "", + pthLoads: bmsLoadsPth, pthRestraints: bmsRestraintsPth, }, { @@ -62,9 +64,7 @@ func Test_main(t *testing.T) { name: "benchmarkCircle", pthStl: "../../files/benchmark-circle.stl", pthSpecs: bmcSpecsPth, - pthLoadPoints: "", - pthLoadDirs: "", - pthLoadMags: "", + pthLoads: bmcLoadsPth, pthRestraints: bmcRestraintsPth, }, { @@ -72,9 +72,7 @@ func Test_main(t *testing.T) { name: "benchmarkPipe", pthStl: "../../files/benchmark-pipe.stl", pthSpecs: bmpSpecsPth, - pthLoadPoints: "", - pthLoadDirs: "", - pthLoadMags: "", + pthLoads: bmpLoadsPth, pthRestraints: bmpRestraintsPth, }, { @@ -82,9 +80,7 @@ func Test_main(t *testing.T) { name: "benchmarkI", pthStl: "../../files/benchmark-I.stl", pthSpecs: bmiSpecsPth, - pthLoadPoints: "", - pthLoadDirs: "", - pthLoadMags: "", + pthLoads: bmiLoadsPth, pthRestraints: bmiRestraintsPth, }, { @@ -92,9 +88,7 @@ func Test_main(t *testing.T) { name: "teapot", pthStl: "../../files/teapot.stl", pthSpecs: teapotSpecsPth, - pthLoadPoints: "", - pthLoadDirs: "", - pthLoadMags: "", + pthLoads: teapotLoadsPth, pthRestraints: teapotRestraintsPth, }, } @@ -142,7 +136,27 @@ func setup() error { if err != nil { return err } - return teapotRestraints() + err = teapotRestraints() + if err != nil { + return err + } + err = bmsLoads() + if err != nil { + return err + } + err = bmcLoads() + if err != nil { + return err + } + err = bmpLoads() + if err != nil { + return err + } + err = bmiLoads() + if err != nil { + return err + } + return teapotLoads() } type Specs struct { @@ -428,3 +442,112 @@ func teapotRestraints() error { return os.WriteFile(teapotRestraintsPth, jsonData, 0644) } + +type Load struct { + LocX float64 + LocY float64 + LocZ float64 + MagX float64 + MagY float64 + MagZ float64 +} + +func bmsLoads() error { + loads := []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + } + + jsonData, err := json.MarshalIndent(loads, "", " ") + if err != nil { + return err + } + + return os.WriteFile(bmsLoadsPth, jsonData, 0644) +} + +func bmcLoads() error { + loads := []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + } + + jsonData, err := json.MarshalIndent(loads, "", " ") + if err != nil { + return err + } + + return os.WriteFile(bmcLoadsPth, jsonData, 0644) +} + +func bmpLoads() error { + loads := []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + } + + jsonData, err := json.MarshalIndent(loads, "", " ") + if err != nil { + return err + } + + return os.WriteFile(bmpLoadsPth, jsonData, 0644) +} + +func bmiLoads() error { + loads := []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + } + + jsonData, err := json.MarshalIndent(loads, "", " ") + if err != nil { + return err + } + + return os.WriteFile(bmiLoadsPth, jsonData, 0644) +} + +func teapotLoads() error { + loads := []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 8, + MagX: 0, + MagY: 0, + MagZ: -10, + }, + } + + jsonData, err := json.MarshalIndent(loads, "", " ") + if err != nil { + return err + } + + return os.WriteFile(teapotLoadsPth, jsonData, 0644) +} From cff15fe7a0db7f1055717ef1e4d16548b3ec03ea Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 16:27:45 +0330 Subject: [PATCH 701/775] Move types --- examples/finite_elements/main.go | 35 +++++++++++++++++++++++++++ examples/finite_elements/main_test.go | 35 --------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 5fbc541ee..3217f3efe 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -42,6 +42,41 @@ const ( Hex20Tet10 // hex20 and tet10 ) +type Specs struct { + MassDensity float64 + YoungModulus float64 + PoissonRatio float64 + GravityConsidered bool + GravityDirectionX float64 + GravityDirectionY float64 + GravityDirectionZ float64 + GravityMagnitude float64 + Resolution int + LayersAllConsidered bool + LayerStart int + LayerEnd int + NonlinearConsidered bool + ExactSurfaceConsidered bool +} + +type Restraint struct { + LocX float64 + LocY float64 + LocZ float64 + IsFixedX bool + IsFixedY bool + IsFixedZ bool +} + +type Load struct { + LocX float64 + LocY float64 + LocZ float64 + MagX float64 + MagY float64 + MagZ float64 +} + // Render SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index fefb45bea..cdc2bd32c 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -159,23 +159,6 @@ func setup() error { return teapotLoads() } -type Specs struct { - MassDensity float64 - YoungModulus float64 - PoissonRatio float64 - GravityConsidered bool - GravityDirectionX float64 - GravityDirectionY float64 - GravityDirectionZ float64 - GravityMagnitude float64 - Resolution int - LayersAllConsidered bool - LayerStart int - LayerEnd int - NonlinearConsidered bool - ExactSurfaceConsidered bool -} - func bmsSpecs() error { specs := Specs{ MassDensity: 7.85e-9, @@ -306,15 +289,6 @@ func teapotSpecs() error { return os.WriteFile(teapotSpecsPth, jsonData, 0644) } -type Restraint struct { - LocX float64 - LocY float64 - LocZ float64 - IsFixedX bool - IsFixedY bool - IsFixedZ bool -} - func bmsRestraints() error { restraints := make([]Restraint, 0) @@ -443,15 +417,6 @@ func teapotRestraints() error { return os.WriteFile(teapotRestraintsPth, jsonData, 0644) } -type Load struct { - LocX float64 - LocY float64 - LocZ float64 - MagX float64 - MagY float64 - MagZ float64 -} - func bmsLoads() error { loads := []Load{ { From dc0e6c2313934463099e2a5cdc28c3e50160881f Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 17:01:44 +0330 Subject: [PATCH 702/775] Load & restraint for a test case --- examples/finite_elements/main_test.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index cdc2bd32c..4999cce0f 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -94,6 +94,13 @@ func Test_main(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + os.Args = []string{ + "executable-name", + tt.pthStl, + tt.pthSpecs, + tt.pthLoads, + tt.pthRestraints, + } main() }) } @@ -399,14 +406,10 @@ func bmiRestraints() error { func teapotRestraints() error { restraints := []Restraint{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, - }, + {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: -2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, } jsonData, err := json.MarshalIndent(restraints, "", " ") @@ -502,7 +505,7 @@ func teapotLoads() error { { LocX: 0, LocY: 0, - LocZ: 8, + LocZ: 8.0, MagX: 0, MagY: 0, MagZ: -10, From 449093f472ab625dbeba0d7d6e1478efd2945b94 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 17:04:16 +0330 Subject: [PATCH 703/775] Rename --- examples/finite_elements/main_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 4999cce0f..ed63b3946 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -95,7 +95,7 @@ func Test_main(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { os.Args = []string{ - "executable-name", + "executable-name-dummy", tt.pthStl, tt.pthSpecs, tt.pthLoads, From 9d578fe8b96ab606a18d21a10acaf9d7c9297cde Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 18:20:52 +0330 Subject: [PATCH 704/775] Handle args --- examples/finite_elements/main.go | 319 ++++---------------------- examples/finite_elements/main_test.go | 15 ++ 2 files changed, 59 insertions(+), 275 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 3217f3efe..f9d44d9d5 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -10,10 +10,10 @@ Output `inp` file is consumable by ABAQUS or CalculiX. package main import ( + "encoding/json" "fmt" "log" "os" - "strconv" "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" @@ -22,26 +22,6 @@ import ( v3 "github.com/deadsy/sdfx/vec/v3" ) -type Benchmark int - -const ( - Square Benchmark = iota + 1 - Circle - Pipe - I -) - -type ElementConfig int - -const ( - Tet4 ElementConfig = iota + 1 // tet4 i.e. 4-node tetrahedron - Tet10 // tet10 i.e. 10-node tetrahedron - Hex8 // hex8 i.e. 8-node hexahedron - Hex20 // hex20 i.e. 20-node hexahedron - Hex8Tet4 // hex8 and tet4 - Hex20Tet10 // hex20 and tet10 -) - type Specs struct { MassDensity float64 YoungModulus float64 @@ -77,173 +57,68 @@ type Load struct { MagZ float64 } -// Render SDF3 to finite elements. +// Render STL to SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - benchmark := Square - elementconfig := Hex8Tet4 + if len(os.Args) != 6 { + log.Fatalf("usage: wrong argument count") + } - // Optional argument from 1 to 4 to specify the benchmark to run. - if len(os.Args) > 1 { - bmint, err := strconv.Atoi(os.Args[1]) - if err != nil { - log.Fatalf("error: %s", err) - } - benchmark = Benchmark(bmint) + pthStl := os.Args[1] + pthSpecs := os.Args[2] + pthLoads := os.Args[3] + pthRestraints := os.Args[4] + pthOut := os.Args[5] + + jsonData, err := os.ReadFile(pthSpecs) + if err != nil { + log.Fatalf("%s", err) } - // Optional argument from 1 to 6 to specify the elements to generate. - if len(os.Args) > 2 { - ecint, err := strconv.Atoi(os.Args[2]) - if err != nil { - log.Fatalf("error: %s", err) - } - elementconfig = ElementConfig(ecint) + var specs Specs + err = json.Unmarshal(jsonData, &specs) + if err != nil { + log.Fatalf("%s", err) + } + + jsonData, err = os.ReadFile(pthLoads) + if err != nil { + log.Fatalf("%s", err) } - // To be set for each benchmark. - var restraints []*mesh.Restraint + var loads []Load + err = json.Unmarshal(jsonData, &loads) + if err != nil { + log.Fatalf("%s", err) + } - // Gravity load is used for benchmarks. So, there is no point load. - location := []v3.Vec{{X: 0, Y: 0, Z: 0}} - loads := []*mesh.Load{ - mesh.NewLoad(location, v3.Vec{X: 0, Y: 0, Z: 0}), + jsonData, err = os.ReadFile(pthRestraints) + if err != nil { + log.Fatalf("%s", err) } - switch benchmark { - case Square: - restraints = benchmarkSquareRestraint() - benchmarkRun("../../files/benchmark-square.stl", 50, 0, 3, restraints, loads, elementconfig) - case Circle: - restraints = benchmarkCircleRestraint() - benchmarkRun("../../files/benchmark-circle.stl", 50, 0, 3, restraints, loads, elementconfig) - case Pipe: - restraints = benchmarkPipeRestraint() - // When resolution is `50`, the pipe benchmark misses some necessary finite elements. - // By incrementing it to `51`, no element is missed. - // There is a bug: https://github.com/deadsy/sdfx/issues/72 - benchmarkRun("../../files/benchmark-pipe.stl", 50, 0, 3, restraints, loads, elementconfig) - case I: - restraints = benchmarkIRestraint() - benchmarkRun("../../files/benchmark-I.stl", 50, 0, 3, restraints, loads, elementconfig) - default: - // If no valid benchmark is picked, run for the teapot. - benchmarkRun("../../files/teapot.stl", 61, 0, 18, restraints, loads, elementconfig) + var restraints []Restraint + err = json.Unmarshal(jsonData, &restraints) + if err != nil { + log.Fatalf("%s", err) } + + Run(pthStl, specs, restraints, loads, pthOut) } -// Benchmark reference: -// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections -func benchmarkRun( - stl string, - resolution int, - layerStart, layerEnd int, - restraints []*mesh.Restraint, - loads []*mesh.Load, - elementconfig ElementConfig, +func Run( + pthStl string, + specs Specs, + restraints []Restraint, + loads []Load, + pthOut string, ) { // create the SDF from the STL mesh - inSdf, err := obj.ImportSTL(stl, 20, 3, 5) + _, err := obj.ImportSTL(pthStl, 20, 3, 5) if err != nil { log.Fatalf("error: %s", err) } - - switch elementconfig { - case Tet4: - { - - err = fe(inSdf, resolution, render.Linear, render.Tetrahedral, "tet4.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - err = feLayers( - inSdf, resolution, render.Linear, render.Tetrahedral, - fmt.Sprintf("tet4--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - } - case Tet10: - { - err = fe(inSdf, resolution, render.Quadratic, render.Tetrahedral, "tet10.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - err = feLayers( - inSdf, resolution, render.Quadratic, render.Tetrahedral, - fmt.Sprintf("tet10--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - } - case Hex8: - { - err = fe(inSdf, resolution, render.Linear, render.Hexahedral, "hex8.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - err = feLayers(inSdf, resolution, render.Linear, render.Hexahedral, - fmt.Sprintf("hex8--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - } - case Hex20: - { - err = fe(inSdf, resolution, render.Quadratic, render.Hexahedral, "hex20.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - err = feLayers(inSdf, resolution, render.Quadratic, render.Hexahedral, - fmt.Sprintf("hex20--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - } - case Hex8Tet4: - { - err = fe(inSdf, resolution, render.Linear, render.HexAndTet, "hex8tet4.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - err = feLayers(inSdf, resolution, render.Linear, render.HexAndTet, - fmt.Sprintf("hex8tet4--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - } - case Hex20Tet10: - { - err = fe(inSdf, resolution, render.Quadratic, render.HexAndTet, "hex20tet10.inp", restraints, loads) - if err != nil { - log.Fatalf("error: %s", err) - } - - err = feLayers(inSdf, resolution, render.Quadratic, render.HexAndTet, - fmt.Sprintf("hex20tet10--layers-%v-to-%v.inp", layerStart, layerEnd), - restraints, loads, layerStart, layerEnd, - ) - if err != nil { - log.Fatalf("error: %s", err) - } - } - } } // Generate finite elements. @@ -282,109 +157,3 @@ func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape // Write just some layers of mesh to file. return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) } - -func benchmarkSquareRestraint() []*mesh.Restraint { - restraints := []*mesh.Restraint{} - - locationPinned := []v3.Vec{} - gap := 1.0 - var y float64 - for y <= 17.32 { - locationPinned = append(locationPinned, v3.Vec{X: 0, Y: y, Z: 0}) - y += gap - } - - restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) - - locationRoller := []v3.Vec{} - y = 0 - for y <= 17.32 { - locationRoller = append(locationRoller, v3.Vec{X: 200, Y: y, Z: 0}) - y += gap - } - - restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) - - return restraints -} - -func benchmarkCircleRestraint() []*mesh.Restraint { - restraints := make([]*mesh.Restraint, 0) - - // The pinned end of 3D beam. - locationPinned := []v3.Vec{ - {X: 0, Y: 0, Z: 0}, - {X: 0, Y: -2.0313, Z: 0.213498}, - {X: 0, Y: -3.97382, Z: 0.844661}, - {X: 0, Y: 2.0313, Z: 0.213498}, - {X: 0, Y: 3.97382, Z: 0.844661}, - } - - restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) - - // The roller end of 3D beam. - locationRoller := []v3.Vec{ - {X: 200, Y: 0, Z: 0}, - {X: 200, Y: -2.0313, Z: 0.213498}, - {X: 200, Y: -3.97382, Z: 0.844661}, - {X: 200, Y: 2.0313, Z: 0.213498}, - {X: 200, Y: 3.97382, Z: 0.844661}, - } - - restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) - - return restraints -} - -func benchmarkPipeRestraint() []*mesh.Restraint { - restraints := make([]*mesh.Restraint, 0) - - // The pinned end of 3D beam. - locationPinned := []v3.Vec{ - {X: 0, Y: 0, Z: 0}, - {X: 0, Y: -2.0313, Z: 0.213498}, - {X: 0, Y: -3.97382, Z: 0.844661}, - {X: 0, Y: 2.0313, Z: 0.213498}, - {X: 0, Y: 3.97382, Z: 0.844661}, - } - - restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) - - // The roller end of 3D beam. - locationRoller := []v3.Vec{ - {X: 200, Y: 0, Z: 0}, - {X: 200, Y: -2.0313, Z: 0.213498}, - {X: 200, Y: -3.97382, Z: 0.844661}, - {X: 200, Y: 2.0313, Z: 0.213498}, - {X: 200, Y: 3.97382, Z: 0.844661}, - } - - restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) - - return restraints -} - -func benchmarkIRestraint() []*mesh.Restraint { - restraints := []*mesh.Restraint{} - - locationPinned := []v3.Vec{} - gap := 1.0 - var y float64 - for y <= 25 { - locationPinned = append(locationPinned, v3.Vec{X: 0, Y: y, Z: 0}) - y += gap - } - - restraints = append(restraints, mesh.NewRestraint(locationPinned, true, true, true)) - - locationRoller := []v3.Vec{} - y = 0 - for y <= 25 { - locationRoller = append(locationRoller, v3.Vec{X: 200, Y: y, Z: 0}) - y += gap - } - - restraints = append(restraints, mesh.NewRestraint(locationRoller, false, true, true)) - - return restraints -} diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index ed63b3946..b7a4b432b 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -36,6 +36,14 @@ var bmpRestraintsPth string = filepath.Join(os.TempDir(), "bmp-restraints.json") var bmiRestraintsPth string = filepath.Join(os.TempDir(), "bmi-restraints.json") var teapotRestraintsPth string = filepath.Join(os.TempDir(), "teapot-restraints.json") +var bmsOutPth string = filepath.Join(os.TempDir(), "bms-out.inp") +var bmcOutPth string = filepath.Join(os.TempDir(), "bmc-out.inp") +var bmpOutPth string = filepath.Join(os.TempDir(), "bmp-out.inp") +var bmiOutPth string = filepath.Join(os.TempDir(), "bmi-out.inp") +var teapotOutPth string = filepath.Join(os.TempDir(), "teapot-out.inp") + +// Benchmark reference: +// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections func Test_main(t *testing.T) { err := setup() if err != nil { @@ -50,6 +58,7 @@ func Test_main(t *testing.T) { pthSpecs string pthLoads string pthRestraints string + pthOut string }{ { skip: false, @@ -58,6 +67,7 @@ func Test_main(t *testing.T) { pthSpecs: bmsSpecsPth, pthLoads: bmsLoadsPth, pthRestraints: bmsRestraintsPth, + pthOut: bmsOutPth, }, { skip: false, @@ -66,6 +76,7 @@ func Test_main(t *testing.T) { pthSpecs: bmcSpecsPth, pthLoads: bmcLoadsPth, pthRestraints: bmcRestraintsPth, + pthOut: bmcOutPth, }, { skip: false, @@ -74,6 +85,7 @@ func Test_main(t *testing.T) { pthSpecs: bmpSpecsPth, pthLoads: bmpLoadsPth, pthRestraints: bmpRestraintsPth, + pthOut: bmpOutPth, }, { skip: false, @@ -82,6 +94,7 @@ func Test_main(t *testing.T) { pthSpecs: bmiSpecsPth, pthLoads: bmiLoadsPth, pthRestraints: bmiRestraintsPth, + pthOut: bmiOutPth, }, { skip: false, @@ -90,6 +103,7 @@ func Test_main(t *testing.T) { pthSpecs: teapotSpecsPth, pthLoads: teapotLoadsPth, pthRestraints: teapotRestraintsPth, + pthOut: teapotOutPth, }, } for _, tt := range tests { @@ -100,6 +114,7 @@ func Test_main(t *testing.T) { tt.pthSpecs, tt.pthLoads, tt.pthRestraints, + tt.pthOut, } main() }) From 9b653931d7f7a00304d11fc50bb10dcc175ac43e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 18:23:33 +0330 Subject: [PATCH 705/775] Rename --- examples/finite_elements/main.go | 6 +++--- examples/finite_elements/main_test.go | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f9d44d9d5..6e48020aa 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -69,7 +69,7 @@ func main() { pthSpecs := os.Args[2] pthLoads := os.Args[3] pthRestraints := os.Args[4] - pthOut := os.Args[5] + pthResult := os.Args[5] jsonData, err := os.ReadFile(pthSpecs) if err != nil { @@ -104,7 +104,7 @@ func main() { log.Fatalf("%s", err) } - Run(pthStl, specs, restraints, loads, pthOut) + Run(pthStl, specs, restraints, loads, pthResult) } func Run( @@ -112,7 +112,7 @@ func Run( specs Specs, restraints []Restraint, loads []Load, - pthOut string, + pthResult string, ) { // create the SDF from the STL mesh _, err := obj.ImportSTL(pthStl, 20, 3, 5) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index b7a4b432b..315a46796 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -36,11 +36,11 @@ var bmpRestraintsPth string = filepath.Join(os.TempDir(), "bmp-restraints.json") var bmiRestraintsPth string = filepath.Join(os.TempDir(), "bmi-restraints.json") var teapotRestraintsPth string = filepath.Join(os.TempDir(), "teapot-restraints.json") -var bmsOutPth string = filepath.Join(os.TempDir(), "bms-out.inp") -var bmcOutPth string = filepath.Join(os.TempDir(), "bmc-out.inp") -var bmpOutPth string = filepath.Join(os.TempDir(), "bmp-out.inp") -var bmiOutPth string = filepath.Join(os.TempDir(), "bmi-out.inp") -var teapotOutPth string = filepath.Join(os.TempDir(), "teapot-out.inp") +var bmsResultPth string = filepath.Join(os.TempDir(), "bms-result.inp") +var bmcResultPth string = filepath.Join(os.TempDir(), "bmc-result.inp") +var bmpResultPth string = filepath.Join(os.TempDir(), "bmp-result.inp") +var bmiResultPth string = filepath.Join(os.TempDir(), "bmi-result.inp") +var teapotResultPth string = filepath.Join(os.TempDir(), "teapot-result.inp") // Benchmark reference: // https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections @@ -58,7 +58,7 @@ func Test_main(t *testing.T) { pthSpecs string pthLoads string pthRestraints string - pthOut string + pthResult string }{ { skip: false, @@ -67,7 +67,7 @@ func Test_main(t *testing.T) { pthSpecs: bmsSpecsPth, pthLoads: bmsLoadsPth, pthRestraints: bmsRestraintsPth, - pthOut: bmsOutPth, + pthResult: bmsResultPth, }, { skip: false, @@ -76,7 +76,7 @@ func Test_main(t *testing.T) { pthSpecs: bmcSpecsPth, pthLoads: bmcLoadsPth, pthRestraints: bmcRestraintsPth, - pthOut: bmcOutPth, + pthResult: bmcResultPth, }, { skip: false, @@ -85,7 +85,7 @@ func Test_main(t *testing.T) { pthSpecs: bmpSpecsPth, pthLoads: bmpLoadsPth, pthRestraints: bmpRestraintsPth, - pthOut: bmpOutPth, + pthResult: bmpResultPth, }, { skip: false, @@ -94,7 +94,7 @@ func Test_main(t *testing.T) { pthSpecs: bmiSpecsPth, pthLoads: bmiLoadsPth, pthRestraints: bmiRestraintsPth, - pthOut: bmiOutPth, + pthResult: bmiResultPth, }, { skip: false, @@ -103,7 +103,7 @@ func Test_main(t *testing.T) { pthSpecs: teapotSpecsPth, pthLoads: teapotLoadsPth, pthRestraints: teapotRestraintsPth, - pthOut: teapotOutPth, + pthResult: teapotResultPth, }, } for _, tt := range tests { @@ -114,7 +114,7 @@ func Test_main(t *testing.T) { tt.pthSpecs, tt.pthLoads, tt.pthRestraints, - tt.pthOut, + tt.pthResult, } main() }) From 70c0f27efe24126d36ef7f8a4116d743f674adeb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 18:27:06 +0330 Subject: [PATCH 706/775] Simplify log --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 6e48020aa..738db9bda 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -117,7 +117,7 @@ func Run( // create the SDF from the STL mesh _, err := obj.ImportSTL(pthStl, 20, 3, 5) if err != nil { - log.Fatalf("error: %s", err) + log.Fatalf("%s", err) } } From 2ec21f78935ef613b8890d0d0fed23255ea96f74 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 18:31:20 +0330 Subject: [PATCH 707/775] Comment --- examples/finite_elements/main.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 738db9bda..4c9910697 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -26,17 +26,17 @@ type Specs struct { MassDensity float64 YoungModulus float64 PoissonRatio float64 - GravityConsidered bool + GravityConsidered bool // If false, gravity direction and magnitude are ignored. GravityDirectionX float64 GravityDirectionY float64 GravityDirectionZ float64 GravityMagnitude float64 - Resolution int - LayersAllConsidered bool + Resolution int // Number of voxels on the longest axis of 3D model AABB. + LayersAllConsidered bool // If true, layer start and layer end are ignored. LayerStart int LayerEnd int - NonlinearConsidered bool - ExactSurfaceConsidered bool + NonlinearConsidered bool // If true, nonlinear finite elements are generated. + ExactSurfaceConsidered bool // Exact surface is approximated by tetrahedral finite elements. } type Restraint struct { From 3af06ba2de4ef61552067f23c8e12b81148485f4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 29 Aug 2023 18:32:33 +0330 Subject: [PATCH 708/775] Comment --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 4c9910697..0f03fd231 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -36,7 +36,7 @@ type Specs struct { LayerStart int LayerEnd int NonlinearConsidered bool // If true, nonlinear finite elements are generated. - ExactSurfaceConsidered bool // Exact surface is approximated by tetrahedral finite elements. + ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. } type Restraint struct { From 7083e9ad5f4c98b214bf78aadd9b1be9e61d666b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 30 Aug 2023 12:19:35 +0330 Subject: [PATCH 709/775] Finish up API --- examples/finite_elements/main.go | 89 +++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 0f03fd231..e952d58c2 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -17,7 +17,6 @@ import ( "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" - "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/sdf/finiteelements/mesh" v3 "github.com/deadsy/sdfx/vec/v3" ) @@ -104,7 +103,10 @@ func main() { log.Fatalf("%s", err) } - Run(pthStl, specs, restraints, loads, pthResult) + err = Run(pthStl, specs, restraints, loads, pthResult) + if err != nil { + log.Fatalf("%s", err) + } } func Run( @@ -113,47 +115,74 @@ func Run( restraints []Restraint, loads []Load, pthResult string, -) { +) error { // create the SDF from the STL mesh - _, err := obj.ImportSTL(pthStl, 20, 3, 5) + inSdf, err := obj.ImportSTL(pthStl, 20, 3, 5) if err != nil { log.Fatalf("%s", err) } -} -// Generate finite elements. -func fe(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, - restraints []*mesh.Restraint, - loads []*mesh.Load, -) error { - // Create a mesh out of finite elements. - m, _ := mesh.NewFem(s, render.NewMarchingCubesFeUniform(resolution, order, shape)) + var order render.Order + if specs.NonlinearConsidered { + order = render.Quadratic + } else { + order = render.Linear + } + + var shape render.Shape + if specs.ExactSurfaceConsidered { + shape = render.HexAndTet + } else { + shape = render.Hexahedral + } + + // Create a mesh of finite elements. + m, _ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) + components := m.Components() fmt.Printf("components count: %v\n", len(components)) for i, component := range components { fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) } - // Write all layers of mesh to file. - return m.WriteInp(pth, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) + if specs.LayersAllConsidered { + // Write all layers of mesh to file. + return m.WriteInp(pthResult, + float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), + restraintsConvert(restraints), + loadsConvert(loads), + v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + ) + } else { + // Write just some layers of mesh to file. + // Generate finite elements. + // Only from a start layer to an end layer along the Z axis. + // Applicable to 3D print analysis that is done layer-by-layer. + return m.WriteInpLayers( + pthResult, + specs.LayerStart, specs.LayerEnd, + float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), + restraintsConvert(restraints), + loadsConvert(loads), + v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + ) + } } -// Generate finite elements. -// Only from a start layer to an end layer along the Z axis. -// Applicable to 3D print analysis that is done layer-by-layer. -func feLayers(s sdf.SDF3, resolution int, order render.Order, shape render.Shape, pth string, - restraints []*mesh.Restraint, - loads []*mesh.Load, - layerStart, layerEnd int, -) error { - // Create a mesh out of finite elements. - m, _ := mesh.NewFem(s, render.NewMarchingCubesFeUniform(resolution, order, shape)) - components := m.Components() - fmt.Printf("components count: %v\n", len(components)) - for i, component := range components { - fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) +func restraintsConvert(rs []Restraint) []*mesh.Restraint { + restraints := make([]*mesh.Restraint, len(rs)) + for i, r := range rs { + restraint := mesh.NewRestraint([]v3.Vec{{X: r.LocX, Y: r.LocY, Z: r.LocZ}}, r.IsFixedX, r.IsFixedY, r.IsFixedZ) + restraints[i] = restraint } + return restraints +} - // Write just some layers of mesh to file. - return m.WriteInpLayers(pth, layerStart, layerEnd, 7.85e-9, 210000, 0.3, restraints, loads, v3.Vec{X: 0, Y: 0, Z: -1}, 9810) +func loadsConvert(ls []Load) []*mesh.Load { + loads := make([]*mesh.Load, len(ls)) + for i, l := range ls { + load := mesh.NewLoad([]v3.Vec{{X: l.LocX, Y: l.LocY, Z: l.LocZ}}, v3.Vec{X: l.MagX, Y: l.MagY, Z: l.MagZ}) + loads[i] = load + } + return loads } From 1e8ba72efd96cc1e61549b21582fef1515f9e22d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 30 Aug 2023 13:47:04 +0330 Subject: [PATCH 710/775] Always consider gravity --- examples/finite_elements/main.go | 1 - examples/finite_elements/main_test.go | 5 ----- 2 files changed, 6 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index e952d58c2..a7668e613 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -25,7 +25,6 @@ type Specs struct { MassDensity float64 YoungModulus float64 PoissonRatio float64 - GravityConsidered bool // If false, gravity direction and magnitude are ignored. GravityDirectionX float64 GravityDirectionY float64 GravityDirectionZ float64 diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 315a46796..42e546b8a 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -186,7 +186,6 @@ func bmsSpecs() error { MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, - GravityConsidered: true, GravityDirectionX: 0, GravityDirectionY: 0, GravityDirectionZ: -1, @@ -212,7 +211,6 @@ func bmcSpecs() error { MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, - GravityConsidered: true, GravityDirectionX: 0, GravityDirectionY: 0, GravityDirectionZ: -1, @@ -238,7 +236,6 @@ func bmpSpecs() error { MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, - GravityConsidered: true, GravityDirectionX: 0, GravityDirectionY: 0, GravityDirectionZ: -1, @@ -264,7 +261,6 @@ func bmiSpecs() error { MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, - GravityConsidered: true, GravityDirectionX: 0, GravityDirectionY: 0, GravityDirectionZ: -1, @@ -290,7 +286,6 @@ func teapotSpecs() error { MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, - GravityConsidered: true, GravityDirectionX: 0, GravityDirectionY: 0, GravityDirectionZ: -1, From f8a1520c0f922c8f8b1eea7a1f8058fe0d4134c5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 30 Aug 2023 13:59:06 +0330 Subject: [PATCH 711/775] More clear test --- examples/finite_elements/main_test.go | 90 +++++++++++++-------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 42e546b8a..e96b22133 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -122,66 +122,66 @@ func Test_main(t *testing.T) { } func setup() error { - err := bmsSpecs() + err := bmsSpecs(bmsSpecsPth) if err != nil { return err } - err = bmcSpecs() + err = bmcSpecs(bmcSpecsPth) if err != nil { return err } - err = bmpSpecs() + err = bmpSpecs(bmpSpecsPth) if err != nil { return err } - err = bmiSpecs() + err = bmiSpecs(bmiSpecsPth) if err != nil { return err } - err = teapotSpecs() + err = teapotSpecs(teapotSpecsPth) if err != nil { return err } - err = bmsRestraints() + err = bmsRestraints(bmsRestraintsPth) if err != nil { return err } - err = bmcRestraints() + err = bmcRestraints(bmcRestraintsPth) if err != nil { return err } - err = bmpRestraints() + err = bmpRestraints(bmpRestraintsPth) if err != nil { return err } - err = bmiRestraints() + err = bmiRestraints(bmiRestraintsPth) if err != nil { return err } - err = teapotRestraints() + err = teapotRestraints(teapotRestraintsPth) if err != nil { return err } - err = bmsLoads() + err = bmsLoads(bmsLoadsPth) if err != nil { return err } - err = bmcLoads() + err = bmcLoads(bmcLoadsPth) if err != nil { return err } - err = bmpLoads() + err = bmpLoads(bmpLoadsPth) if err != nil { return err } - err = bmiLoads() + err = bmiLoads(bmiLoadsPth) if err != nil { return err } - return teapotLoads() + return teapotLoads(teapotLoadsPth) } -func bmsSpecs() error { +func bmsSpecs(pth string) error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -203,10 +203,10 @@ func bmsSpecs() error { return err } - return os.WriteFile(bmsSpecsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmcSpecs() error { +func bmcSpecs(pth string) error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -228,10 +228,10 @@ func bmcSpecs() error { return err } - return os.WriteFile(bmcSpecsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmpSpecs() error { +func bmpSpecs(pth string) error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -253,10 +253,10 @@ func bmpSpecs() error { return err } - return os.WriteFile(bmpSpecsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmiSpecs() error { +func bmiSpecs(pth string) error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -278,10 +278,10 @@ func bmiSpecs() error { return err } - return os.WriteFile(bmiSpecsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func teapotSpecs() error { +func teapotSpecs(pth string) error { specs := Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -303,10 +303,10 @@ func teapotSpecs() error { return err } - return os.WriteFile(teapotSpecsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmsRestraints() error { +func bmsRestraints(pth string) error { restraints := make([]Restraint, 0) gap := 1.0 @@ -343,10 +343,10 @@ func bmsRestraints() error { return err } - return os.WriteFile(bmsRestraintsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmcRestraints() error { +func bmcRestraints(pth string) error { restraints := []Restraint{ {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, @@ -365,10 +365,10 @@ func bmcRestraints() error { return err } - return os.WriteFile(bmcRestraintsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmpRestraints() error { +func bmpRestraints(pth string) error { restraints := []Restraint{ {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, @@ -387,10 +387,10 @@ func bmpRestraints() error { return err } - return os.WriteFile(bmpRestraintsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmiRestraints() error { +func bmiRestraints(pth string) error { restraints := make([]Restraint, 0) gap := 1.0 @@ -411,10 +411,10 @@ func bmiRestraints() error { return err } - return os.WriteFile(bmiRestraintsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func teapotRestraints() error { +func teapotRestraints(pth string) error { restraints := []Restraint{ {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, @@ -427,10 +427,10 @@ func teapotRestraints() error { return err } - return os.WriteFile(teapotRestraintsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmsLoads() error { +func bmsLoads(pth string) error { loads := []Load{ { LocX: 0, @@ -447,10 +447,10 @@ func bmsLoads() error { return err } - return os.WriteFile(bmsLoadsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmcLoads() error { +func bmcLoads(pth string) error { loads := []Load{ { LocX: 0, @@ -467,10 +467,10 @@ func bmcLoads() error { return err } - return os.WriteFile(bmcLoadsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmpLoads() error { +func bmpLoads(pth string) error { loads := []Load{ { LocX: 0, @@ -487,10 +487,10 @@ func bmpLoads() error { return err } - return os.WriteFile(bmpLoadsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func bmiLoads() error { +func bmiLoads(pth string) error { loads := []Load{ { LocX: 0, @@ -507,10 +507,10 @@ func bmiLoads() error { return err } - return os.WriteFile(bmiLoadsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } -func teapotLoads() error { +func teapotLoads(pth string) error { loads := []Load{ { LocX: 0, @@ -527,5 +527,5 @@ func teapotLoads() error { return err } - return os.WriteFile(teapotLoadsPth, jsonData, 0644) + return os.WriteFile(pth, jsonData, 0644) } From 0b9e8d44b4d0d4988e640212d31d954c04cb0a53 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 1 Sep 2023 09:45:31 +0330 Subject: [PATCH 712/775] No global var --- examples/finite_elements/main_test.go | 87 ++++++++++----------------- 1 file changed, 32 insertions(+), 55 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index e96b22133..8fc414476 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -18,39 +18,9 @@ import ( "testing" ) -var bmsSpecsPth string = filepath.Join(os.TempDir(), "bms-specs.json") -var bmcSpecsPth string = filepath.Join(os.TempDir(), "bmc-specs.json") -var bmpSpecsPth string = filepath.Join(os.TempDir(), "bmp-specs.json") -var bmiSpecsPth string = filepath.Join(os.TempDir(), "bmi-specs.json") -var teapotSpecsPth string = filepath.Join(os.TempDir(), "teapot-specs.json") - -var bmsLoadsPth string = filepath.Join(os.TempDir(), "bms-loads.json") -var bmcLoadsPth string = filepath.Join(os.TempDir(), "bmc-loads.json") -var bmpLoadsPth string = filepath.Join(os.TempDir(), "bmp-loads.json") -var bmiLoadsPth string = filepath.Join(os.TempDir(), "bmi-loads.json") -var teapotLoadsPth string = filepath.Join(os.TempDir(), "teapot-loads.json") - -var bmsRestraintsPth string = filepath.Join(os.TempDir(), "bms-restraints.json") -var bmcRestraintsPth string = filepath.Join(os.TempDir(), "bmc-restraints.json") -var bmpRestraintsPth string = filepath.Join(os.TempDir(), "bmp-restraints.json") -var bmiRestraintsPth string = filepath.Join(os.TempDir(), "bmi-restraints.json") -var teapotRestraintsPth string = filepath.Join(os.TempDir(), "teapot-restraints.json") - -var bmsResultPth string = filepath.Join(os.TempDir(), "bms-result.inp") -var bmcResultPth string = filepath.Join(os.TempDir(), "bmc-result.inp") -var bmpResultPth string = filepath.Join(os.TempDir(), "bmp-result.inp") -var bmiResultPth string = filepath.Join(os.TempDir(), "bmi-result.inp") -var teapotResultPth string = filepath.Join(os.TempDir(), "teapot-result.inp") - // Benchmark reference: // https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections func Test_main(t *testing.T) { - err := setup() - if err != nil { - t.Error(err) - return - } - tests := []struct { skip bool name string @@ -63,51 +33,58 @@ func Test_main(t *testing.T) { { skip: false, name: "benchmarkSquare", - pthStl: "../../files/benchmark-square.stl", - pthSpecs: bmsSpecsPth, - pthLoads: bmsLoadsPth, - pthRestraints: bmsRestraintsPth, - pthResult: bmsResultPth, + pthStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), + pthSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), + pthLoads: filepath.Join(os.TempDir(), "bms-loads.json"), + pthRestraints: filepath.Join(os.TempDir(), "bms-restraints.json"), + pthResult: filepath.Join(os.TempDir(), "bms-result.inp"), }, { skip: false, name: "benchmarkCircle", - pthStl: "../../files/benchmark-circle.stl", - pthSpecs: bmcSpecsPth, - pthLoads: bmcLoadsPth, - pthRestraints: bmcRestraintsPth, - pthResult: bmcResultPth, + pthStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), + pthSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), + pthLoads: filepath.Join(os.TempDir(), "bmc-loads.json"), + pthRestraints: filepath.Join(os.TempDir(), "bmc-restraints.json"), + pthResult: filepath.Join(os.TempDir(), "bmc-result.inp"), }, { skip: false, name: "benchmarkPipe", - pthStl: "../../files/benchmark-pipe.stl", - pthSpecs: bmpSpecsPth, - pthLoads: bmpLoadsPth, - pthRestraints: bmpRestraintsPth, - pthResult: bmpResultPth, + pthStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), + pthSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), + pthLoads: filepath.Join(os.TempDir(), "bmp-loads.json"), + pthRestraints: filepath.Join(os.TempDir(), "bmp-restraints.json"), + pthResult: filepath.Join(os.TempDir(), "bmp-result.inp"), }, { skip: false, name: "benchmarkI", - pthStl: "../../files/benchmark-I.stl", - pthSpecs: bmiSpecsPth, - pthLoads: bmiLoadsPth, - pthRestraints: bmiRestraintsPth, - pthResult: bmiResultPth, + pthStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), + pthSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), + pthLoads: filepath.Join(os.TempDir(), "bmi-loads.json"), + pthRestraints: filepath.Join(os.TempDir(), "bmi-restraints.json"), + pthResult: filepath.Join(os.TempDir(), "bmi-result.inp"), }, { skip: false, name: "teapot", - pthStl: "../../files/teapot.stl", - pthSpecs: teapotSpecsPth, - pthLoads: teapotLoadsPth, - pthRestraints: teapotRestraintsPth, - pthResult: teapotResultPth, + pthStl: filepath.Join("..", "..", "files", "teapot.stl"), + pthSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), + pthLoads: filepath.Join(os.TempDir(), "teapot-loads.json"), + pthRestraints: filepath.Join(os.TempDir(), "teapot-restraints.json"), + pthResult: filepath.Join(os.TempDir(), "teapot-result.inp"), }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + err := setup() + if err != nil { + t.Error(err) + return + } + os.Args = []string{ "executable-name-dummy", tt.pthStl, From 8e6ce9688bbf1e7655dfa858f3a957bd6deb86f0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 1 Sep 2023 10:22:44 +0330 Subject: [PATCH 713/775] Test case fields: specs, restraints, loads --- examples/finite_elements/main_test.go | 649 ++++++++++---------------- 1 file changed, 239 insertions(+), 410 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 8fc414476..3ebe06c35 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -29,6 +29,9 @@ func Test_main(t *testing.T) { pthLoads string pthRestraints string pthResult string + specs Specs + restraints []Restraint + loads []Load }{ { skip: false, @@ -38,6 +41,64 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "bms-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bms-restraints.json"), pthResult: filepath.Join(os.TempDir(), "bms-result.inp"), + specs: Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + restraints: func() []Restraint { + restraints := make([]Restraint, 0) + + gap := 1.0 + var y float64 + for y <= 17.32 { + restraint := Restraint{ + LocX: 0, + LocY: y, + LocZ: 0, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + } + restraints = append(restraints, restraint) + y += gap + } + + y = 0 + for y <= 17.32 { + restraint := Restraint{ + LocX: 200, + LocY: y, + LocZ: 0, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, + } + restraints = append(restraints, restraint) + y += gap + } + return restraints + }(), + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, }, { skip: false, @@ -47,6 +108,43 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "bmc-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmc-restraints.json"), pthResult: filepath.Join(os.TempDir(), "bmc-result.inp"), + specs: Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + restraints: []Restraint{ + {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, }, { skip: false, @@ -56,6 +154,43 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "bmp-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmp-restraints.json"), pthResult: filepath.Join(os.TempDir(), "bmp-result.inp"), + specs: Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + restraints: []Restraint{ + {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, }, { skip: false, @@ -65,6 +200,49 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "bmi-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmi-restraints.json"), pthResult: filepath.Join(os.TempDir(), "bmi-result.inp"), + specs: Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + restraints: func() []Restraint { + restraints := make([]Restraint, 0) + + gap := 1.0 + var y float64 + for y <= 25 { + restraints = append(restraints, Restraint{LocX: 0, LocY: y, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}) + y += gap + } + + y = 0 + for y <= 25 { + restraints = append(restraints, Restraint{LocX: 200, LocY: y, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}) + y += gap + } + + return restraints + }(), + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, }, { skip: false, @@ -74,12 +252,72 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "teapot-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "teapot-restraints.json"), pthResult: filepath.Join(os.TempDir(), "teapot-result.inp"), + specs: Specs{ + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayersAllConsidered: true, + LayerStart: -1, // Negative means all layers. + LayerEnd: -1, // Negative means all layers. + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + restraints: []Restraint{ + {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: -2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 8.0, + MagX: 0, + MagY: 0, + MagZ: -10, + }, + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := setup() + jsonData, err := json.MarshalIndent(tt.specs, "", " ") + if err != nil { + t.Error(err) + return + } + err = os.WriteFile(tt.pthSpecs, jsonData, 0644) + if err != nil { + t.Error(err) + return + } + + jsonData, err = json.MarshalIndent(tt.restraints, "", " ") + if err != nil { + t.Error(err) + return + } + + err = os.WriteFile(tt.pthRestraints, jsonData, 0644) + if err != nil { + t.Error(err) + return + } + + jsonData, err = json.MarshalIndent(tt.loads, "", " ") + if err != nil { + t.Error(err) + return + } + + err = os.WriteFile(tt.pthLoads, jsonData, 0644) if err != nil { t.Error(err) return @@ -97,412 +335,3 @@ func Test_main(t *testing.T) { }) } } - -func setup() error { - err := bmsSpecs(bmsSpecsPth) - if err != nil { - return err - } - err = bmcSpecs(bmcSpecsPth) - if err != nil { - return err - } - err = bmpSpecs(bmpSpecsPth) - if err != nil { - return err - } - err = bmiSpecs(bmiSpecsPth) - if err != nil { - return err - } - err = teapotSpecs(teapotSpecsPth) - if err != nil { - return err - } - err = bmsRestraints(bmsRestraintsPth) - if err != nil { - return err - } - err = bmcRestraints(bmcRestraintsPth) - if err != nil { - return err - } - err = bmpRestraints(bmpRestraintsPth) - if err != nil { - return err - } - err = bmiRestraints(bmiRestraintsPth) - if err != nil { - return err - } - err = teapotRestraints(teapotRestraintsPth) - if err != nil { - return err - } - err = bmsLoads(bmsLoadsPth) - if err != nil { - return err - } - err = bmcLoads(bmcLoadsPth) - if err != nil { - return err - } - err = bmpLoads(bmpLoadsPth) - if err != nil { - return err - } - err = bmiLoads(bmiLoadsPth) - if err != nil { - return err - } - return teapotLoads(teapotLoadsPth) -} - -func bmsSpecs(pth string) error { - specs := Specs{ - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - } - - jsonData, err := json.MarshalIndent(specs, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmcSpecs(pth string) error { - specs := Specs{ - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - } - - jsonData, err := json.MarshalIndent(specs, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmpSpecs(pth string) error { - specs := Specs{ - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - } - - jsonData, err := json.MarshalIndent(specs, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmiSpecs(pth string) error { - specs := Specs{ - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - } - - jsonData, err := json.MarshalIndent(specs, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func teapotSpecs(pth string) error { - specs := Specs{ - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - } - - jsonData, err := json.MarshalIndent(specs, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmsRestraints(pth string) error { - restraints := make([]Restraint, 0) - - gap := 1.0 - var y float64 - for y <= 17.32 { - restraint := Restraint{ - LocX: 0, - LocY: y, - LocZ: 0, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, - } - restraints = append(restraints, restraint) - y += gap - } - - y = 0 - for y <= 17.32 { - restraint := Restraint{ - LocX: 200, - LocY: y, - LocZ: 0, - IsFixedX: false, - IsFixedY: true, - IsFixedZ: true, - } - restraints = append(restraints, restraint) - y += gap - } - - jsonData, err := json.MarshalIndent(restraints, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmcRestraints(pth string) error { - restraints := []Restraint{ - {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - } - - jsonData, err := json.MarshalIndent(restraints, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmpRestraints(pth string) error { - restraints := []Restraint{ - {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - } - - jsonData, err := json.MarshalIndent(restraints, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmiRestraints(pth string) error { - restraints := make([]Restraint, 0) - - gap := 1.0 - var y float64 - for y <= 25 { - restraints = append(restraints, Restraint{LocX: 0, LocY: y, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}) - y += gap - } - - y = 0 - for y <= 25 { - restraints = append(restraints, Restraint{LocX: 200, LocY: y, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}) - y += gap - } - - jsonData, err := json.MarshalIndent(restraints, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func teapotRestraints(pth string) error { - restraints := []Restraint{ - {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: -2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - } - - jsonData, err := json.MarshalIndent(restraints, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmsLoads(pth string) error { - loads := []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - } - - jsonData, err := json.MarshalIndent(loads, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmcLoads(pth string) error { - loads := []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - } - - jsonData, err := json.MarshalIndent(loads, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmpLoads(pth string) error { - loads := []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - } - - jsonData, err := json.MarshalIndent(loads, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func bmiLoads(pth string) error { - loads := []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - } - - jsonData, err := json.MarshalIndent(loads, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} - -func teapotLoads(pth string) error { - loads := []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 8.0, - MagX: 0, - MagY: 0, - MagZ: -10, - }, - } - - jsonData, err := json.MarshalIndent(loads, "", " ") - if err != nil { - return err - } - - return os.WriteFile(pth, jsonData, 0644) -} From 0ea304bbb9b27e85e7d5c83fdd4c392744576229 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 1 Sep 2023 10:27:14 +0330 Subject: [PATCH 714/775] Consistent arg order --- examples/finite_elements/main_test.go | 102 +++++++++++++------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 3ebe06c35..54d569337 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -30,8 +30,8 @@ func Test_main(t *testing.T) { pthRestraints string pthResult string specs Specs - restraints []Restraint loads []Load + restraints []Restraint }{ { skip: false, @@ -56,6 +56,16 @@ func Test_main(t *testing.T) { NonlinearConsidered: false, ExactSurfaceConsidered: true, }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, restraints: func() []Restraint { restraints := make([]Restraint, 0) @@ -89,16 +99,6 @@ func Test_main(t *testing.T) { } return restraints }(), - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - }, }, { skip: false, @@ -123,6 +123,16 @@ func Test_main(t *testing.T) { NonlinearConsidered: false, ExactSurfaceConsidered: true, }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, restraints: []Restraint{ {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, @@ -135,16 +145,6 @@ func Test_main(t *testing.T) { {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, }, - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - }, }, { skip: false, @@ -169,6 +169,16 @@ func Test_main(t *testing.T) { NonlinearConsidered: false, ExactSurfaceConsidered: true, }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, restraints: []Restraint{ {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, @@ -181,16 +191,6 @@ func Test_main(t *testing.T) { {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, }, - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - }, }, { skip: false, @@ -215,6 +215,16 @@ func Test_main(t *testing.T) { NonlinearConsidered: false, ExactSurfaceConsidered: true, }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, restraints: func() []Restraint { restraints := make([]Restraint, 0) @@ -233,16 +243,6 @@ func Test_main(t *testing.T) { return restraints }(), - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - }, }, { skip: false, @@ -267,12 +267,6 @@ func Test_main(t *testing.T) { NonlinearConsidered: false, ExactSurfaceConsidered: true, }, - restraints: []Restraint{ - {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: -2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - }, loads: []Load{ { LocX: 0, @@ -283,6 +277,12 @@ func Test_main(t *testing.T) { MagZ: -10, }, }, + restraints: []Restraint{ + {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: -2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + }, }, } @@ -299,25 +299,25 @@ func Test_main(t *testing.T) { return } - jsonData, err = json.MarshalIndent(tt.restraints, "", " ") + jsonData, err = json.MarshalIndent(tt.loads, "", " ") if err != nil { t.Error(err) return } - err = os.WriteFile(tt.pthRestraints, jsonData, 0644) + err = os.WriteFile(tt.pthLoads, jsonData, 0644) if err != nil { t.Error(err) return } - jsonData, err = json.MarshalIndent(tt.loads, "", " ") + jsonData, err = json.MarshalIndent(tt.restraints, "", " ") if err != nil { t.Error(err) return } - err = os.WriteFile(tt.pthLoads, jsonData, 0644) + err = os.WriteFile(tt.pthRestraints, jsonData, 0644) if err != nil { t.Error(err) return From 939449b7548b82b912fcd8a0d98683bcc70c9d8b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 1 Sep 2023 10:32:21 +0330 Subject: [PATCH 715/775] Comment --- examples/finite_elements/main.go | 2 +- examples/finite_elements/main_test.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index a7668e613..f0109334c 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -2,7 +2,7 @@ /* Finite elements from triangle mesh. -Output `inp` file is consumable by ABAQUS or CalculiX. +The result `inp` file is consumable by ABAQUS or CalculiX. */ //----------------------------------------------------------------------------- diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 54d569337..5c1520521 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -3,7 +3,7 @@ /* Finite elements from triangle mesh. -Output `inp` file is consumable by ABAQUS or CalculiX. +The result `inp` file is consumable by ABAQUS or CalculiX. */ @@ -24,11 +24,11 @@ func Test_main(t *testing.T) { tests := []struct { skip bool name string - pthStl string - pthSpecs string - pthLoads string - pthRestraints string - pthResult string + pthStl string // Input STL file. + pthSpecs string // To be created by test. + pthLoads string // To be created by test. + pthRestraints string // To be created by test. + pthResult string // Result file, consumable by ABAQUS or CalculiX. specs Specs loads []Load restraints []Restraint From f5ae31477c5bd6ab32524943d542e4e5d2650d54 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 1 Sep 2023 10:50:29 +0330 Subject: [PATCH 716/775] Comment --- examples/finite_elements/main_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 5c1520521..108f9e11c 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -30,7 +30,7 @@ func Test_main(t *testing.T) { pthRestraints string // To be created by test. pthResult string // Result file, consumable by ABAQUS or CalculiX. specs Specs - loads []Load + loads []Load // If load is zero, gravity would be the dominant force. restraints []Restraint }{ { From 285afe3c44351438dde0e4d6dcbf30eeb7901269 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 1 Sep 2023 11:18:30 +0330 Subject: [PATCH 717/775] Import `tetrahedron-table` --- go.mod | 1 + go.sum | 2 + render/marchfehelper.go | 2469 --------------------------------------- render/marchfelogic.go | 5 +- 4 files changed, 6 insertions(+), 2471 deletions(-) diff --git a/go.mod b/go.mod index 8a7722ec0..162ce37fe 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/deadsy/sdfx go 1.13 require ( + github.com/Megidd/tetrahedron-table v0.0.0-20230901074008-499ef3fcef87 github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b github.com/dhconnelly/rtreego v1.1.0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 diff --git a/go.sum b/go.sum index e8f997521..fb0ff4b69 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zum git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Megidd/tetrahedron-table v0.0.0-20230901074008-499ef3fcef87 h1:Q46IyMIux8zFiWM1cP4mXhPldL+z0jLGeKy/2tQTlXQ= +github.com/Megidd/tetrahedron-table v0.0.0-20230901074008-499ef3fcef87/go.mod h1:TlCbcNZKX8/kXirrkWTy7AUgEJoryHM9ahRHLHZtsBc= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= diff --git a/render/marchfehelper.go b/render/marchfehelper.go index 44972d7bd..eabf5a6da 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -313,2472 +313,3 @@ func degenerateTriangles(a, b, c, d v3.Vec) bool { } //----------------------------------------------------------------------------- - -// Specify the edges & corners used to create the tetrahedra. -// Keep the index from 0 to 11 for edges, -// but shift the index for corners. -// Corners were originally indexed from 0 to 7. -// So, corners would be indexed from 0+12 to 7+12 i.e. from 12 to 19. -// Manually created by: -// https://github.com/Megidd/tetrahedron-table -var mcTetrahedronTable = [256][]int{ - // 0b00000000 case 0: no cube corner has zero/negative value. - {}, - // 0b00000001 case 1: first cube corner has zero/negative value. - {12, 0, 3, 8}, - // 0b00000010 case 2 - {13, 1, 0, 9}, - // 0b00000011 case 3 - { - 12, 13, 3, 8, - 13, 1, 3, 8, - 13, 1, 8, 9, - }, - // 0b00000100 case 4 - {14, 2, 1, 10}, - // 0b00000101 case 5 - { - 12, 0, 3, 8, - 14, 2, 1, 10, - }, - // 0b00000110 case 6 - { - 13, 14, 0, 9, - 14, 2, 0, 9, - 14, 2, 9, 10, - }, - // 0b00000111 case 7 - { - 12, 13, 3, 8, - 13, 2, 3, 8, - 13, 14, 2, 8, - 14, 2, 8, 10, - 13, 14, 8, 10, - 13, 10, 8, 9, - }, - // 0b00001000 case 8 - { - 15, 3, 2, 11, - }, - // 0b00001001 case 9 - { - 12, 0, 2, 11, - 12, 2, 15, 11, - 12, 0, 11, 8, - }, - // 0b00001010 case 10 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - }, - // 0b00001011 case 11 - { - 15, 12, 2, 11, - 12, 1, 2, 11, - 12, 13, 1, 11, - 13, 1, 11, 9, - 12, 13, 11, 9, - 11, 12, 9, 8, - }, - // 0b00001100 case 12 - { - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00001101 case 13 - { - 12, 0, 1, 8, - 12, 1, 14, 8, - 1, 14, 8, 10, - 14, 15, 12, 8, - 14, 15, 8, 10, - 10, 15, 8, 11, - }, - // 0b00001110 case 14 - { - 0, 15, 3, 11, - 0, 14, 15, 11, - 0, 14, 11, 9, - 0, 13, 14, 9, - 14, 11, 9, 10, - }, - // 0b00001111 case 15 - { - 12, 13, 14, 10, - 12, 13, 10, 9, - 12, 9, 10, 8, - 12, 14, 15, 8, - 14, 15, 8, 10, - 15, 8, 10, 11, - }, - // 0b00010000 case 16 - {8, 4, 7, 16}, - // 0b00010001 case 17 - { - 12, 0, 3, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b00010010 case 18 - { - 8, 4, 7, 16, - 13, 1, 0, 9, - }, - // 0b00010011 case 19 - { - 3, 12, 1, 7, - 12, 13, 1, 7, - 12, 13, 7, 16, - 13, 1, 7, 9, - 13, 7, 16, 9, - 16, 9, 7, 4, - }, - // 0b00010100 case 20 - { - 8, 4, 7, 16, - 1, 14, 2, 10, - }, - // 0b00010101 case 21 - { - 1, 14, 2, 10, - 3, 12, 0, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b00010110 case 22 - { - 8, 4, 7, 16, - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 10, - }, - // 0b00010111 case 23 - { - 3, 12, 2, 7, - 12, 13, 2, 7, - 13, 2, 7, 4, - 13, 2, 4, 9, - 12, 13, 7, 16, - 16, 13, 7, 4, - 13, 14, 2, 9, - 14, 2, 9, 10, - }, - // 0b00011000 case 24 - { - 8, 4, 7, 16, - 2, 15, 3, 11, - }, - // 0b00011001 case 25 - { - 12, 0, 2, 4, - 12, 2, 15, 4, - 2, 15, 4, 11, - 12, 4, 15, 11, - 12, 4, 11, 7, - 12, 4, 7, 16, - }, - // 0b00011010 case 26 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - 8, 4, 7, 16, - }, - // 0b00011011 case 27 - { - 12, 2, 15, 11, - 12, 1, 2, 11, - 12, 13, 1, 11, - 13, 1, 11, 9, - 12, 13, 11, 9, - 12, 9, 11, 4, - 12, 4, 11, 16, - 11, 16, 4, 7, - }, - // 0b00011100 case 28 - { - 8, 4, 7, 16, - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00011101 case 29 - { - 1, 14, 15, 10, - 15, 1, 10, 11, - 12, 1, 15, 11, - 12, 0, 1, 4, - 12, 1, 11, 4, - 12, 4, 11, 7, - 12, 4, 7, 16, - }, - // 0b00011110 case 30 - { - 8, 4, 7, 16, - 13, 14, 0, 9, - 14, 3, 0, 9, - 14, 15, 3, 9, - 15, 3, 9, 11, - 14, 15, 9, 11, - 14, 11, 9, 10, - }, - // 0b00011111 case 31 - { - 13, 14, 15, 11, - 13, 14, 11, 9, - 14, 11, 9, 10, - 12, 13, 15, 9, - 12, 9, 15, 11, - 12, 9, 11, 7, - 12, 9, 7, 16, - 16, 9, 7, 4, - }, - // 0b00100000 case 32 - {9, 5, 4, 17}, - // 0b00100001 case 33 - { - 12, 0, 3, 8, - 9, 5, 4, 17, - }, - // 0b00100010 case 34 - { - 0, 13, 1, 5, - 0, 13, 5, 4, - 4, 13, 5, 17, - }, - // 0b00100011 case 35 - { - 13, 1, 3, 5, - 13, 3, 12, 5, - 12, 5, 3, 4, - 12, 4, 3, 8, - 12, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00100100 case 36 - { - 1, 14, 2, 10, - 9, 5, 4, 17, - }, - // 0b00100101 case 37 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 4, 9, 5, 17, - }, - // 0b00100110 case 38 - { - 0, 14, 2, 4, - 14, 2, 4, 5, - 14, 2, 5, 10, - 0, 13, 14, 4, - 13, 14, 4, 5, - 13, 5, 4, 17, - }, - // 0b00100111 case 39 - { - 13, 14, 2, 10, - 12, 13, 2, 10, - 12, 2, 3, 10, - 12, 10, 3, 8, - 12, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 4, - 13, 5, 4, 17, - }, - // 0b00101000 case 40 - { - 9, 5, 4, 17, - 2, 15, 3, 11, - }, - // 0b00101001 case 41 - { - 9, 5, 4, 17, - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - }, - // 0b00101010 case 42 - { - 2, 15, 3, 11, - 0, 13, 1, 4, - 4, 13, 1, 5, - 4, 13, 5, 17, - }, - // 0b00101011 case 43 - { - 2, 15, 12, 11, - 11, 12, 2, 8, - 12, 1, 2, 8, - 12, 13, 1, 8, - 8, 1, 2, 5, - 13, 1, 8, 5, - 8, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00101100 case 44 - { - 9, 5, 4, 17, - 1, 14, 3, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00101101 case 45 - { - 9, 5, 4, 17, - 1, 14, 0, 10, - 14, 12, 0, 10, - 12, 0, 10, 8, - 14, 15, 12, 10, - 15, 12, 10, 8, - 15, 8, 10, 11, - }, - // 0b00101110 case 46 - { - 14, 15, 3, 11, - 14, 3, 0, 11, - 0, 14, 11, 5, - 14, 11, 5, 10, - 0, 13, 14, 5, - 0, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b00101111 case 47 - { - 14, 15, 12, 8, - 14, 15, 8, 10, - 15, 8, 10, 11, - 12, 13, 14, 10, - 12, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 4, - 13, 5, 4, 17, - }, - // 0b00110000 case 48 - { - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - }, - // 0b00110001 case 49 - { - 3, 12, 0, 5, - 3, 12, 5, 7, - 12, 0, 7, 16, - 0, 5, 7, 16, - 0, 5, 16, 9, - 9, 5, 16, 17, - }, - // 0b00110010 case 50 - { - 0, 13, 1, 7, - 13, 1, 7, 5, - 0, 13, 5, 17, - 0, 5, 7, 17, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b00110011 case 51 - { - 12, 1, 3, 5, - 3, 12, 5, 7, - 12, 13, 1, 5, - 12, 13, 5, 17, - 12, 17, 5, 7, - 12, 17, 7, 16, - }, - // 0b00110100 case 52 - { - 1, 14, 2, 10, - 7, 8, 5, 16, - 8, 9, 5, 16, - 16, 9, 5, 17, - }, - // 0b00110101 case 53 - { - 1, 14, 2, 10, - 3, 12, 0, 5, - 3, 12, 5, 7, - 0, 9, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 12, - 12, 17, 7, 16, - }, - // 0b00110110 case 54 - { - 13, 14, 2, 10, - 0, 13, 2, 10, - 0, 10, 2, 8, - 0, 13, 10, 8, - 13, 10, 8, 5, - 13, 5, 8, 17, - 8, 17, 5, 7, - 8, 17, 7, 16, - }, - // 0b00110111 case 55 - { - 13, 14, 2, 10, - 13, 2, 3, 10, - 13, 10, 3, 5, - 12, 13, 3, 5, - 12, 13, 5, 17, - 3, 12, 5, 7, - 12, 17, 5, 7, - 12, 17, 7, 16, - }, - // 0b00111000 case 56 - { - 15, 3, 2, 11, - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - }, - // 0b00111001 case 57 - { - 12, 0, 2, 9, - 15, 12, 2, 9, - 2, 15, 9, 11, - 15, 12, 9, 11, - 12, 9, 11, 7, - 12, 9, 7, 16, - 9, 7, 16, 5, - 9, 5, 16, 17, - }, - // 0b00111010 case 58 - { - 15, 3, 2, 11, - 0, 13, 1, 8, - 13, 1, 8, 7, - 13, 1, 7, 5, - 13, 7, 8, 16, - 13, 7, 16, 5, - 13, 5, 16, 17, - }, - // 0b00111011 case 59 - { - 12, 13, 1, 17, - 12, 17, 1, 5, - 12, 5, 1, 7, - 12, 17, 5, 7, - 12, 17, 7, 16, - 2, 12, 1, 7, - 15, 12, 2, 7, - 15, 7, 2, 11, - }, - // 0b00111100 case 60 - { - 8, 5, 7, 16, - 8, 9, 5, 16, - 9, 5, 16, 17, - 14, 3, 1, 10, - 14, 15, 3, 10, - 15, 3, 10, 11, - }, - // 0b00111101 case 61 - { - 0, 9, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 16, - 0, 16, 7, 12, - 12, 0, 11, 7, - 14, 0, 1, 10, - 12, 0, 15, 11, - 14, 15, 0, 11, - 14, 11, 0, 10, - }, - // 0b00111110 case 62 - { - 15, 3, 0, 11, - 14, 15, 0, 11, - 14, 11, 0, 10, - 14, 0, 13, 10, - 0, 13, 10, 5, - 0, 13, 5, 17, - 0, 17, 5, 7, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b00111111 case 63 - { - 12, 14, 15, 11, - 12, 14, 11, 10, - 12, 13, 14, 10, - 11, 12, 10, 7, - 12, 13, 10, 7, - 12, 13, 7, 16, - 13, 10, 7, 5, - 13, 5, 7, 17, - 13, 7, 16, 17, - }, - // 0b01000000 case 64 - {10, 6, 5, 18}, - // 0b01000001 case 65 - { - 12, 0, 3, 8, - 10, 6, 5, 18, - }, - // 0b01000010 case 66 - { - 0, 13, 1, 9, - 10, 6, 5, 18, - }, - // 0b01000011 case 67 - { - 10, 6, 5, 18, - 3, 12, 1, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - }, - // 0b01000100 case 68 - { - 1, 14, 2, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01000101 case 69 - { - 12, 0, 3, 8, - 14, 2, 1, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01000110 case 70 - { - 0, 13, 2, 6, - 0, 13, 6, 9, - 13, 14, 2, 6, - 13, 14, 6, 9, - 9, 14, 6, 5, - 14, 6, 5, 18, - }, - // 0b01000111 case 71 - { - 3, 12, 2, 8, - 12, 13, 2, 8, - 13, 2, 8, 9, - 13, 14, 2, 9, - 9, 2, 8, 5, - 9, 14, 2, 5, - 14, 2, 5, 6, - 14, 6, 5, 18, - }, - // 0b01001000 case 72 - { - 10, 6, 5, 18, - 15, 3, 2, 11, - }, - // 0b01001001 case 73 - { - 10, 6, 5, 18, - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - }, - // 0b01001010 case 74 - { - 0, 13, 1, 9, - 2, 15, 3, 11, - 10, 6, 5, 18, - }, - // 0b01001011 case 75 - { - 10, 6, 5, 18, - 2, 15, 1, 11, - 15, 13, 1, 11, - 13, 1, 11, 9, - 15, 12, 13, 11, - 11, 12, 13, 9, - 11, 12, 9, 8, - }, - // 0b01001100 case 76 - { - 14, 15, 3, 11, - 1, 14, 3, 11, - 1, 11, 3, 5, - 1, 14, 11, 5, - 5, 14, 11, 6, - 5, 14, 6, 18, - }, - // 0b01001101 case 77 - { - 12, 0, 15, 8, - 15, 8, 0, 11, - 14, 0, 1, 5, - 14, 15, 0, 11, - 14, 0, 5, 6, - 14, 11, 0, 6, - 14, 6, 5, 18, - }, - // 0b01001110 case 78 - { - 0, 13, 14, 9, - 14, 15, 3, 11, - 14, 3, 0, 9, - 14, 11, 3, 6, - 14, 3, 9, 5, - 14, 6, 3, 5, - 14, 6, 5, 18, - }, - // 0b01001111 case 79 - { - 15, 12, 13, 8, - 13, 15, 8, 11, - 13, 11, 8, 9, - 13, 14, 15, 9, - 14, 15, 9, 11, - 9, 14, 11, 5, - 14, 11, 5, 6, - 14, 6, 5, 18, - }, - // 0b01010000 case 80 - { - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01010001 case 81 - { - 10, 6, 5, 18, - 12, 0, 3, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - }, - // 0b01010010 case 82 - { - 13, 1, 0, 9, - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01010011 case 83 - { - 10, 6, 5, 18, - 12, 13, 1, 9, - 3, 12, 1, 9, - 3, 9, 1, 7, - 3, 12, 9, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - }, - // 0b01010100 case 84 - { - 8, 4, 7, 16, - 14, 2, 1, 6, - 1, 14, 6, 5, - 5, 14, 6, 18, - }, - // 0b01010101 case 85 - { - 3, 12, 0, 7, - 12, 0, 7, 4, - 12, 4, 7, 16, - 1, 14, 2, 5, - 14, 2, 5, 6, - 5, 14, 6, 18, - }, - // 0b01010110 case 86 - { - 8, 4, 7, 16, - 0, 13, 2, 6, - 0, 13, 6, 9, - 13, 14, 2, 6, - 13, 14, 6, 9, - 14, 6, 9, 5, - 14, 6, 5, 18, - }, - // 0b01010111 case 87 - { - 13, 2, 3, 9, - 13, 3, 12, 9, - 13, 14, 2, 9, - 14, 2, 9, 6, - 3, 12, 9, 7, - 12, 9, 7, 4, - 14, 6, 9, 5, - 12, 4, 7, 16, - 14, 6, 5, 18, - }, - // 0b01011000 case 88 - { - 8, 4, 7, 16, - 10, 6, 5, 18, - 15, 3, 2, 11, - }, - // 0b01011001 case 89 - { - 10, 6, 5, 18, - 2, 15, 0, 4, - 2, 15, 4, 11, - 15, 12, 0, 4, - 15, 12, 4, 11, - 11, 12, 4, 7, - 7, 12, 4, 16, - }, - // 0b01011010 case 90 - { - 13, 1, 0, 9, - 2, 15, 3, 11, - 8, 4, 7, 16, - 10, 6, 5, 18, - }, - // 0b01011011 case 91 - { - 10, 6, 5, 18, - 15, 1, 2, 11, - 15, 13, 1, 11, - 13, 1, 11, 9, - 15, 12, 13, 11, - 12, 13, 11, 9, - 12, 9, 11, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - }, - // 0b01011100 case 92 - { - 8, 4, 7, 16, - 1, 15, 3, 5, - 15, 3, 5, 6, - 15, 3, 6, 11, - 1, 14, 15, 6, - 1, 14, 6, 5, - 14, 6, 5, 18, - }, - // 0b01011101 case 93 - { - 15, 0, 1, 11, - 15, 12, 0, 11, - 1, 14, 15, 11, - 11, 12, 0, 4, - 11, 1, 14, 5, - 11, 12, 4, 7, - 11, 5, 14, 6, - 14, 6, 5, 18, - 12, 4, 7, 16, - }, - // 0b01011110 case 94 - { - 8, 4, 7, 16, - 13, 3, 0, 9, - 13, 15, 3, 9, - 15, 3, 9, 11, - 13, 14, 15, 9, - 14, 15, 9, 11, - 14, 11, 9, 5, - 14, 11, 5, 6, - 14, 6, 5, 18, - }, - // 0b01011111 case 95 - { - 15, 12, 13, 11, - 11, 12, 13, 9, - 11, 12, 9, 7, - 12, 9, 7, 4, - 12, 4, 7, 16, - 13, 14, 15, 9, - 14, 15, 9, 11, - 9, 14, 11, 5, - 5, 14, 11, 6, - 14, 6, 5, 18, - }, - // 0b01100000 case 96 - { - 9, 10, 4, 17, - 10, 6, 4, 17, - 10, 6, 17, 18, - }, - // 0b01100001 case 97 - { - 12, 0, 3, 8, - 4, 9, 6, 17, - 9, 10, 6, 17, - 17, 10, 6, 18, - }, - // 0b01100010 case 98 - { - 0, 13, 1, 6, - 1, 10, 6, 18, - 13, 1, 6, 18, - 0, 13, 6, 4, - 13, 18, 6, 4, - 13, 18, 4, 17, - }, - // 0b01100011 case 99 - { - 3, 12, 1, 8, - 12, 13, 1, 8, - 8, 13, 1, 17, - 1, 8, 17, 4, - 1, 6, 8, 4, - 1, 4, 17, 6, - 1, 6, 17, 10, - 17, 10, 6, 18, - }, - // 0b01100100 case 100 - { - 1, 14, 2, 6, - 1, 2, 4, 6, - 1, 14, 6, 18, - 1, 18, 6, 4, - 1, 18, 4, 9, - 9, 18, 4, 17, - }, - // 0b01100101 case 101 - { - 3, 12, 0, 8, - 1, 14, 2, 9, - 9, 14, 2, 4, - 14, 2, 4, 6, - 9, 14, 4, 17, - 14, 6, 4, 17, - 14, 6, 17, 18, - }, - // 0b01100110 case 102 - { - 0, 13, 2, 4, - 13, 14, 2, 4, - 14, 2, 4, 6, - 14, 18, 6, 4, - 14, 18, 4, 13, - 13, 18, 4, 17, - }, - // 0b01100111 case 103 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 13, 14, 2, 8, - 14, 2, 8, 4, - 13, 14, 8, 4, - 14, 2, 4, 6, - 13, 14, 4, 17, - 14, 4, 17, 6, - 14, 6, 17, 18, - }, - // 0b01101000 case 104 - { - 2, 15, 3, 11, - 4, 9, 6, 17, - 9, 10, 6, 17, - 10, 6, 17, 18, - }, - // 0b01101001 case 105 - { - 2, 15, 0, 11, - 15, 12, 0, 11, - 12, 0, 11, 8, - 4, 9, 6, 17, - 9, 10, 6, 17, - 10, 6, 17, 18, - }, - // 0b01101010 case 106 - { - 2, 15, 3, 11, - 0, 13, 1, 6, - 0, 13, 6, 4, - 1, 10, 6, 4, - 13, 1, 4, 17, - 10, 6, 4, 18, - 17, 1, 4, 10, - 17, 10, 4, 18, - }, - // 0b01101011 case 107 - { - 15, 1, 2, 11, - 15, 12, 1, 11, - 12, 1, 11, 8, - 12, 13, 1, 8, - 8, 13, 1, 4, - 13, 1, 4, 17, - 1, 6, 4, 17, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01101100 case 108 - { - 1, 14, 3, 9, - 14, 15, 3, 9, - 15, 3, 9, 11, - 14, 15, 9, 11, - 14, 11, 9, 6, - 14, 6, 9, 18, - 9, 18, 6, 4, - 4, 9, 18, 17, - }, - // 0b01101101 case 109 - { - 12, 0, 1, 8, - 15, 12, 1, 8, - 15, 8, 1, 11, - 14, 15, 1, 11, - 1, 14, 11, 6, - 1, 14, 6, 18, - 1, 18, 6, 4, - 1, 18, 4, 17, - 1, 17, 4, 9, - }, - // 0b01101110 case 110 - { - 14, 15, 3, 11, - 0, 14, 3, 11, - 0, 13, 14, 11, - 0, 13, 11, 6, - 13, 14, 11, 6, - 13, 14, 6, 18, - 0, 13, 6, 4, - 13, 18, 6, 4, - 13, 18, 4, 17, - }, - // 0b01101111 case 111 - { - 15, 12, 13, 11, - 13, 14, 15, 11, - 12, 13, 11, 8, - 8, 13, 14, 4, - 14, 8, 4, 11, - 14, 11, 4, 6, - 13, 14, 4, 17, - 14, 4, 17, 6, - 14, 6, 17, 18, - }, - // 0b01110000 case 112 - { - 8, 9, 10, 7, - 9, 10, 7, 6, - 8, 9, 7, 16, - 9, 10, 6, 18, - 9, 7, 16, 17, - 9, 6, 7, 17, - 9, 18, 6, 17, - }, - // 0b01110001 case 113 - { - 12, 0, 3, 7, - 12, 0, 7, 16, - 0, 9, 10, 7, - 0, 9, 7, 16, - 9, 10, 16, 17, - 10, 7, 16, 17, - 10, 7, 17, 6, - 10, 6, 17, 18, - }, - // 0b01110010 case 114 - { - 0, 13, 1, 10, - 0, 13, 10, 8, - 13, 10, 8, 6, - 13, 6, 8, 7, - 13, 10, 6, 18, - 13, 7, 8, 16, - 13, 6, 7, 17, - 13, 18, 6, 17, - 13, 7, 16, 17, - }, - // 0b01110011 case 115 - { - 3, 12, 13, 7, - 12, 13, 7, 16, - 13, 1, 3, 7, - 13, 1, 16, 17, - 1, 7, 16, 6, - 1, 6, 16, 17, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01110100 case 116 - { - 1, 14, 2, 6, - 1, 14, 6, 18, - 1, 18, 6, 7, - 1, 8, 9, 16, - 1, 7, 8, 16, - 1, 18, 7, 16, - 1, 18, 16, 9, - 9, 18, 16, 17, - }, - // 0b01110101 case 117 - { - 3, 12, 0, 9, - 3, 12, 9, 7, - 12, 9, 7, 16, - 9, 7, 16, 17, - 9, 6, 7, 17, - 1, 14, 2, 9, - 14, 2, 9, 6, - 14, 6, 9, 17, - 14, 6, 17, 18, - }, - // 0b01110110 case 118 - { - 13, 14, 2, 6, - 0, 13, 2, 6, - 13, 14, 6, 18, - 0, 13, 18, 17, - 0, 17, 18, 6, - 0, 17, 6, 7, - 0, 17, 7, 16, - 0, 7, 8, 16, - }, - // 0b01110111 case 119 - { - 12, 2, 3, 7, - 12, 14, 2, 7, - 14, 2, 7, 6, - 12, 13, 14, 7, - 12, 13, 7, 16, - 14, 6, 7, 18, - 14, 18, 7, 16, - 13, 14, 16, 18, - 13, 18, 16, 17, - }, - // 0b01111000 case 120 - { - 2, 15, 3, 11, - 8, 9, 10, 7, - 9, 10, 7, 6, - 9, 10, 6, 18, - 8, 9, 7, 16, - 9, 18, 6, 17, - 9, 6, 7, 17, - 9, 7, 16, 17, - }, - // 0b01111001 case 121 - { - 15, 0, 2, 7, - 15, 7, 2, 11, - 15, 12, 0, 7, - 12, 0, 7, 16, - 16, 0, 7, 9, - 16, 9, 7, 17, - 9, 10, 7, 17, - 10, 7, 17, 18, - 10, 7, 18, 6, - }, - // 0b01111010 case 122 - { - 15, 3, 2, 11, - 0, 13, 1, 10, - 0, 13, 10, 8, - 13, 10, 8, 6, - 8, 13, 6, 7, - 13, 6, 7, 17, - 13, 10, 6, 17, - 13, 7, 8, 17, - 17, 10, 6, 18, - 17, 7, 8, 16, - }, - // 0b01111011 case 123 - { - 15, 1, 2, 11, - 15, 12, 1, 11, - 12, 13, 1, 11, - 13, 1, 11, 7, - 12, 13, 11, 7, - 12, 13, 7, 16, - 13, 7, 16, 17, - 13, 1, 7, 17, - 1, 7, 17, 6, - 1, 6, 17, 10, - 10, 6, 17, 18, - }, - // 0b01111100 case 124 - { - 3, 11, 6, 15, - 1, 15, 3, 6, - 1, 14, 15, 6, - 1, 14, 6, 18, - 1, 18, 6, 9, - 9, 18, 6, 17, - 8, 9, 6, 17, - 8, 17, 6, 7, - 8, 17, 7, 16, - }, - // 0b01111101 case 125 - { - 12, 0, 1, 9, - 12, 1, 14, 9, - 12, 14, 15, 9, - 12, 9, 15, 17, - 14, 15, 9, 17, - 15, 12, 17, 16, - 15, 17, 14, 18, - 15, 16, 17, 7, - 15, 17, 18, 6, - 15, 7, 17, 11, - 15, 17, 6, 11, - 11, 6, 7, 17, - }, - // 0b01111110 case 126 - { - 15, 3, 0, 11, - 14, 15, 0, 11, - 0, 14, 11, 6, - 0, 13, 14, 6, - 13, 14, 6, 18, - 0, 13, 18, 17, - 0, 18, 6, 17, - 0, 17, 6, 7, - 0, 17, 7, 8, - 8, 17, 7, 16, - }, - // 0b01111111 case 127 - { - 6, 7, 11, 15, - 12, 13, 15, 7, - 13, 14, 15, 7, - 14, 15, 7, 6, - 13, 14, 7, 6, - 13, 14, 6, 18, - 12, 13, 7, 16, - 13, 18, 6, 17, - 13, 6, 7, 17, - 13, 7, 16, 17, - }, - // 0b10000000 case 128 - { - 11, 7, 6, 19, - }, - // 0b10000001 case 129 - { - 3, 12, 0, 8, - 11, 7, 6, 19, - }, - // 0b10000010 case 130 - { - 0, 13, 1, 9, - 11, 7, 6, 19, - }, - // 0b10000011 case 131 - { - 11, 7, 6, 19, - 3, 12, 1, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - }, - // 0b10000100 case 132 - { - 1, 14, 2, 10, - 11, 7, 6, 19, - }, - // 0b10000101 case 133 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 11, 7, 6, 19, - }, - // 0b10000110 case 134 - { - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 10, - 11, 7, 6, 19, - }, - // 0b10000111 case 135 - { - 12, 2, 3, 8, - 12, 14, 2, 8, - 14, 2, 8, 10, - 12, 13, 14, 8, - 13, 14, 8, 10, - 13, 10, 8, 9, - 11, 7, 6, 19, - }, - // 0b10001000 case 136 - { - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001001 case 137 - { - 2, 15, 0, 6, - 15, 12, 0, 6, - 12, 0, 6, 7, - 12, 0, 7, 8, - 15, 12, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001010 case 138 - { - 0, 13, 1, 9, - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10001011 case 139 - { - 12, 13, 1, 9, - 12, 9, 1, 8, - 12, 1, 2, 8, - 2, 8, 1, 7, - 2, 7, 1, 6, - 2, 15, 12, 8, - 2, 15, 8, 7, - 2, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10001100 case 140 - { - 15, 3, 1, 7, - 14, 15, 1, 7, - 1, 14, 7, 6, - 1, 14, 6, 10, - 14, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10001101 case 141 - { - 14, 0, 1, 10, - 14, 12, 0, 10, - 12, 0, 10, 8, - 14, 15, 12, 10, - 15, 12, 10, 8, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - }, - // 0b10001110 case 142 - { - 0, 13, 14, 9, - 14, 0, 9, 10, - 14, 15, 0, 10, - 15, 3, 0, 10, - 10, 3, 0, 7, - 10, 15, 3, 7, - 10, 15, 7, 6, - 6, 15, 7, 19, - }, - // 0b10001111 case 143 - { - 14, 15, 12, 8, - 14, 15, 8, 10, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - 12, 13, 14, 10, - 12, 13, 10, 8, - 8, 13, 10, 9, - }, - // 0b10010000 case 144 - { - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010001 case 145 - { - 3, 12, 0, 4, - 3, 4, 0, 6, - 12, 4, 6, 16, - 3, 12, 6, 16, - 3, 16, 6, 19, - 3, 19, 6, 11, - }, - // 0b10010010 case 146 - { - 0, 13, 1, 9, - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010011 case 147 - { - 3, 13, 1, 9, - 3, 12, 13, 9, - 3, 12, 9, 6, - 12, 9, 6, 4, - 3, 12, 4, 16, - 3, 16, 4, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10010100 case 148 - { - 1, 14, 2, 10, - 11, 8, 6, 19, - 8, 4, 6, 19, - 8, 4, 19, 16, - }, - // 0b10010101 case 149 - { - 1, 14, 2, 10, - 3, 12, 0, 11, - 12, 0, 11, 6, - 12, 6, 11, 19, - 0, 6, 19, 4, - 12, 0, 19, 4, - 12, 4, 19, 16, - }, - // 0b10010110 case 150 - { - 13, 14, 0, 9, - 14, 2, 0, 9, - 14, 2, 9, 10, - 11, 8, 6, 19, - 8, 6, 19, 4, - 8, 4, 19, 16, - }, - // 0b10010111 case 151 - { - 3, 14, 2, 10, - 3, 13, 14, 10, - 3, 13, 10, 9, - 3, 12, 13, 9, - 3, 12, 9, 4, - 3, 12, 4, 16, - 3, 16, 4, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10011000 case 152 - { - 2, 15, 3, 8, - 2, 15, 8, 4, - 15, 8, 4, 16, - 2, 15, 4, 6, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011001 case 153 - { - 12, 0, 2, 4, - 15, 12, 2, 4, - 2, 15, 4, 6, - 12, 4, 15, 16, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011010 case 154 - { - 0, 13, 1, 9, - 2, 15, 3, 8, - 2, 15, 8, 4, - 15, 8, 4, 16, - 2, 15, 4, 6, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011011 case 155 - { - 2, 13, 1, 9, - 2, 13, 9, 4, - 12, 13, 2, 4, - 15, 12, 2, 4, - 2, 15, 4, 6, - 15, 12, 4, 16, - 15, 16, 4, 6, - 15, 16, 6, 19, - }, - // 0b10011100 case 156 - { - 14, 3, 1, 8, - 14, 8, 1, 10, - 14, 15, 3, 8, - 14, 15, 8, 10, - 10, 15, 8, 6, - 15, 8, 6, 19, - 6, 19, 8, 4, - 19, 8, 4, 16, - }, - // 0b10011101 case 157 - { - 14, 0, 1, 10, - 14, 15, 0, 10, - 15, 12, 0, 10, - 12, 0, 10, 6, - 15, 12, 10, 6, - 12, 0, 6, 4, - 15, 12, 6, 19, - 12, 4, 6, 19, - 12, 4, 19, 16, - }, - // 0b10011110 case 158 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 10, - 14, 15, 3, 10, - 15, 3, 10, 6, - 15, 3, 6, 19, - 3, 6, 19, 4, - 3, 4, 19, 8, - 8, 4, 19, 16, - }, - // 0b10011111 case 159 - { - 12, 13, 14, 10, - 12, 13, 10, 9, - 12, 14, 15, 10, - 15, 9, 10, 6, - 15, 12, 9, 6, - 12, 9, 6, 4, - 15, 12, 6, 19, - 12, 6, 19, 4, - 12, 4, 19, 16, - }, - // 0b10100000 case 160 - { - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100001 case 161 - { - 3, 12, 0, 8, - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100010 case 162 - { - 0, 13, 1, 4, - 13, 1, 4, 5, - 4, 13, 5, 17, - 11, 7, 6, 19, - }, - // 0b10100011 case 163 - { - 3, 13, 1, 5, - 3, 12, 13, 5, - 12, 13, 5, 17, - 3, 17, 5, 4, - 3, 12, 17, 4, - 3, 12, 4, 8, - 11, 7, 6, 19, - }, - // 0b10100100 case 164 - { - 1, 14, 2, 10, - 11, 7, 6, 19, - 9, 5, 4, 17, - }, - // 0b10100101 case 165 - { - 3, 12, 0, 8, - 1, 14, 2, 10, - 9, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100110 case 166 - { - 14, 2, 0, 10, - 13, 14, 0, 10, - 0, 13, 10, 5, - 0, 13, 5, 4, - 13, 5, 4, 17, - 11, 7, 6, 19, - }, - // 0b10100111 case 167 - { - 11, 7, 6, 19, - 3, 14, 2, 10, - 3, 12, 14, 10, - 3, 12, 10, 8, - 12, 13, 14, 10, - 12, 13, 10, 8, - 8, 13, 10, 5, - 8, 13, 5, 4, - 13, 5, 4, 17, - }, - // 0b10101000 case 168 - { - 9, 5, 4, 17, - 2, 15, 3, 6, - 15, 3, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101001 case 169 - { - 9, 5, 4, 17, - 2, 12, 0, 6, - 12, 0, 6, 7, - 12, 0, 7, 8, - 2, 15, 12, 6, - 15, 12, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101010 case 170 - { - 0, 13, 1, 4, - 13, 1, 4, 5, - 13, 5, 4, 17, - 2, 15, 3, 6, - 15, 3, 6, 7, - 15, 7, 6, 19, - }, - // 0b10101011 case 171 - { - 2, 12, 1, 8, - 12, 13, 1, 8, - 2, 15, 12, 8, - 8, 13, 1, 5, - 8, 13, 5, 4, - 4, 13, 5, 17, - 2, 15, 8, 6, - 15, 8, 6, 7, - 6, 15, 7, 19, - }, - // 0b10101100 case 172 - { - 9, 5, 4, 17, - 1, 15, 3, 7, - 1, 14, 15, 7, - 1, 14, 7, 6, - 1, 14, 6, 10, - 14, 15, 7, 6, - 15, 7, 6, 19, - }, - // 0b10101101 case 173 - { - 9, 5, 4, 17, - 1, 12, 0, 8, - 14, 12, 1, 8, - 14, 15, 12, 8, - 14, 8, 1, 10, - 14, 15, 8, 10, - 10, 15, 8, 6, - 6, 15, 8, 7, - 6, 15, 7, 19, - }, - // 0b10101110 case 174 - { - 13, 14, 0, 10, - 14, 3, 0, 10, - 14, 15, 3, 10, - 0, 13, 10, 5, - 0, 5, 10, 4, - 0, 13, 5, 4, - 13, 5, 4, 17, - 15, 3, 10, 7, - 15, 7, 10, 6, - 15, 7, 6, 19, - }, - // 0b10101111 case 175 - { - 12, 13, 14, 10, - 12, 14, 15, 10, - 12, 13, 10, 8, - 10, 15, 12, 8, - 10, 15, 8, 6, - 15, 8, 6, 7, - 15, 7, 6, 19, - 13, 10, 8, 4, - 13, 10, 4, 5, - 13, 5, 4, 17, - }, - // 0b10110000 case 176 - { - 11, 8, 9, 5, - 11, 8, 5, 6, - 8, 9, 5, 17, - 8, 6, 11, 19, - 8, 17, 5, 16, - 8, 5, 6, 16, - 8, 6, 19, 16, - }, - // 0b10110001 case 177 - { - 12, 0, 3, 11, - 11, 12, 0, 9, - 11, 12, 9, 6, - 12, 9, 6, 5, - 12, 6, 11, 19, - 12, 9, 5, 17, - 12, 17, 5, 16, - 12, 5, 6, 16, - 12, 6, 19, 16, - }, - // 0b10110010 case 178 - { - 0, 13, 1, 5, - 0, 13, 5, 17, - 0, 17, 5, 6, - 0, 17, 6, 11, - 11, 17, 6, 19, - 0, 17, 11, 19, - 0, 19, 11, 8, - 0, 17, 19, 8, - 8, 17, 19, 16, - }, - // 0b10110011 case 179 - { - 3, 13, 1, 5, - 3, 12, 13, 5, - 12, 13, 5, 17, - 3, 12, 17, 16, - 3, 17, 5, 16, - 3, 16, 5, 6, - 3, 16, 6, 11, - 16, 6, 11, 19, - }, - // 0b10110100 case 180 - { - 11, 8, 9, 5, - 11, 8, 5, 6, - 8, 9, 5, 17, - 8, 17, 5, 16, - 8, 5, 6, 16, - 8, 6, 11, 19, - 8, 6, 19, 16, - 1, 14, 2, 10, - }, - // 0b10110101 case 181 - { - 1, 14, 2, 10, - 3, 12, 0, 9, - 3, 12, 9, 11, - 11, 12, 9, 5, - 11, 12, 5, 6, - 12, 9, 5, 17, - 11, 12, 6, 19, - 12, 17, 5, 16, - 12, 5, 6, 16, - 12, 6, 19, 16, - }, - // 0b10110110 case 182 - { - 13, 14, 2, 10, - 0, 13, 2, 10, - 0, 10, 2, 5, - 0, 13, 10, 5, - 0, 13, 5, 17, - 0, 17, 5, 8, - 8, 17, 5, 16, - 11, 8, 5, 16, - 11, 16, 5, 6, - 11, 16, 6, 19, - }, - // 0b10110111 case 183 - { - 3, 14, 2, 10, - 3, 13, 14, 10, - 3, 12, 13, 10, - 3, 12, 10, 5, - 12, 13, 10, 5, - 12, 13, 5, 17, - 3, 12, 17, 16, - 3, 17, 5, 16, - 3, 16, 5, 6, - 3, 16, 6, 11, - 11, 16, 6, 19, - }, - // 0b10111000 case 184 - { - 8, 9, 5, 17, - 8, 17, 5, 16, - 2, 15, 3, 8, - 2, 15, 8, 5, - 2, 15, 5, 6, - 15, 8, 5, 6, - 6, 8, 5, 16, - 6, 15, 8, 19, - 6, 19, 8, 16, - }, - // 0b10111001 case 185 - { - 2, 15, 0, 6, - 15, 12, 0, 6, - 15, 12, 6, 19, - 12, 0, 19, 16, - 0, 6, 19, 16, - 0, 6, 16, 5, - 0, 5, 16, 9, - 16, 9, 5, 17, - }, - // 0b10111010 case 186 - { - 0, 13, 1, 8, - 13, 1, 8, 5, - 8, 13, 5, 17, - 8, 17, 5, 16, - 8, 16, 5, 6, - 2, 15, 3, 8, - 2, 15, 8, 6, - 15, 8, 6, 16, - 15, 16, 6, 19, - }, - // 0b10111011 case 187 - { - 2, 13, 1, 5, - 2, 12, 13, 5, - 12, 13, 5, 17, - 12, 17, 5, 16, - 12, 2, 15, 5, - 2, 15, 5, 6, - 15, 12, 5, 16, - 15, 16, 5, 6, - 15, 16, 6, 19, - }, - // 0b10111100 case 188 - { - 14, 3, 1, 6, - 1, 14, 6, 10, - 14, 15, 3, 6, - 15, 3, 6, 19, - 3, 6, 19, 8, - 8, 6, 19, 16, - 8, 6, 16, 9, - 9, 6, 16, 5, - 9, 5, 16, 17, - }, - // 0b10111101 case 189 - { - 14, 0, 1, 10, - 14, 12, 0, 10, - 14, 15, 12, 10, - 12, 0, 10, 6, - 10, 15, 12, 6, - 6, 15, 12, 19, - 12, 0, 19, 16, - 0, 6, 19, 16, - 0, 6, 16, 5, - 0, 5, 16, 9, - 16, 9, 5, 17, - }, - // 0b10111110 case 190 - { - 0, 15, 3, 8, - 0, 14, 15, 8, - 0, 13, 14, 8, - 8, 14, 15, 16, - 14, 15, 16, 19, - 13, 14, 8, 16, - 13, 14, 16, 17, - 14, 16, 17, 5, - 14, 16, 5, 10, - 10, 16, 5, 6, - 14, 19, 16, 10, - 10, 19, 16, 6, - }, - // 0b10111111 case 191 - { - 13, 15, 12, 16, - 13, 14, 15, 16, - 13, 14, 16, 17, - 14, 15, 16, 19, - 14, 16, 17, 5, - 14, 19, 16, 6, - 14, 6, 16, 10, - 14, 16, 5, 10, - 10, 6, 16, 5, - }, - // 0b11000000 case 192 - { - 10, 11, 5, 18, - 18, 11, 5, 7, - 11, 7, 18, 19, - }, - // 0b11000001 case 193 - { - 3, 12, 0, 8, - 5, 10, 11, 18, - 5, 18, 11, 7, - 11, 7, 18, 19, - }, - // 0b11000010 case 194 - { - 0, 13, 1, 9, - 10, 11, 5, 18, - 11, 7, 5, 18, - 11, 7, 18, 19, - }, - // 0b11000011 case 195 - { - 12, 1, 3, 8, - 12, 13, 1, 8, - 13, 1, 8, 9, - 10, 11, 5, 18, - 11, 7, 5, 18, - 11, 7, 18, 19, - }, - // 0b11000100 case 196 - { - 1, 14, 2, 7, - 1, 14, 7, 5, - 14, 2, 5, 18, - 2, 7, 5, 18, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11000101 case 197 - { - 1, 14, 2, 7, - 1, 14, 7, 5, - 14, 2, 5, 18, - 2, 7, 5, 18, - 2, 7, 18, 11, - 11, 7, 18, 19, - 3, 12, 0, 8, - }, - // 0b11000110 case 198 - { - 0, 13, 2, 9, - 13, 14, 2, 9, - 14, 2, 9, 5, - 14, 2, 5, 18, - 2, 9, 5, 7, - 2, 5, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11000111 case 199 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 8, 13, 2, 9, - 13, 14, 2, 9, - 9, 14, 2, 5, - 14, 2, 5, 18, - 2, 5, 18, 7, - 7, 18, 2, 11, - 18, 11, 7, 19, - }, - // 0b11001000 case 200 - { - 2, 15, 3, 10, - 15, 3, 10, 5, - 5, 10, 15, 18, - 5, 15, 3, 7, - 5, 18, 15, 7, - 18, 15, 7, 19, - }, - // 0b11001001 case 201 - { - 12, 0, 2, 8, - 15, 12, 2, 8, - 2, 15, 8, 7, - 2, 15, 7, 19, - 2, 7, 8, 5, - 2, 19, 7, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001010 case 202 - { - 0, 13, 1, 9, - 2, 15, 3, 5, - 15, 3, 5, 7, - 2, 15, 7, 19, - 2, 7, 5, 19, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001011 case 203 - { - 2, 13, 1, 9, - 2, 12, 13, 9, - 2, 12, 9, 8, - 2, 15, 12, 8, - 2, 15, 8, 7, - 2, 15, 7, 19, - 2, 19, 7, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11001100 case 204 - { - 1, 14, 3, 5, - 14, 15, 3, 5, - 15, 3, 5, 7, - 14, 15, 5, 18, - 15, 7, 5, 18, - 15, 7, 18, 19, - }, - // 0b11001101 case 205 - { - 1, 12, 0, 8, - 1, 15, 12, 8, - 1, 15, 8, 7, - 1, 14, 15, 7, - 14, 15, 7, 19, - 14, 7, 1, 5, - 14, 7, 5, 19, - 14, 19, 5, 18, - }, - // 0b11001110 case 206 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 5, - 14, 15, 3, 5, - 14, 15, 5, 18, - 15, 3, 5, 7, - 15, 7, 5, 18, - 15, 7, 18, 19, - }, - // 0b11001111 case 207 - { - 15, 12, 13, 8, - 13, 15, 8, 9, - 14, 15, 13, 9, - 15, 8, 9, 7, - 14, 15, 9, 7, - 14, 7, 9, 5, - 15, 7, 14, 19, - 14, 19, 7, 5, - 14, 19, 5, 18, - }, - // 0b11010000 case 208 - { - 10, 11, 8, 4, - 10, 11, 4, 5, - 11, 8, 4, 16, - 11, 5, 10, 18, - 11, 16, 4, 19, - 11, 4, 5, 19, - 11, 5, 18, 19, - }, - // 0b11010001 case 209 - { - 3, 12, 0, 5, - 12, 0, 5, 4, - 12, 4, 5, 16, - 3, 12, 5, 16, - 3, 16, 5, 11, - 11, 16, 5, 19, - 11, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11010010 case 210 - { - 0, 13, 1, 9, - 10, 11, 8, 4, - 10, 11, 4, 5, - 10, 11, 5, 18, - 11, 8, 4, 16, - 11, 5, 18, 19, - 11, 4, 5, 19, - 11, 16, 4, 19, - }, - // 0b11010011 case 211 - { - 3, 13, 1, 4, - 13, 1, 4, 9, - 3, 12, 13, 4, - 3, 12, 4, 16, - 3, 16, 4, 11, - 11, 16, 4, 19, - 10, 11, 4, 19, - 10, 19, 4, 5, - 10, 19, 5, 18, - }, - // 0b11010100 case 212 - { - 1, 14, 2, 5, - 14, 2, 5, 18, - 2, 5, 18, 4, - 2, 4, 18, 8, - 2, 8, 18, 11, - 18, 8, 4, 16, - 18, 8, 16, 11, - 18, 11, 16, 19, - }, - // 0b11010101 case 213 - { - 12, 0, 3, 11, - 12, 0, 11, 4, - 12, 4, 11, 16, - 4, 11, 16, 19, - 11, 19, 4, 5, - 11, 19, 5, 18, - 1, 14, 2, 11, - 1, 14, 11, 5, - 14, 11, 5, 18, - }, - // 0b11010110 case 214 - { - 13, 2, 0, 5, - 0, 13, 5, 9, - 13, 14, 2, 5, - 5, 14, 2, 18, - 5, 18, 2, 11, - 5, 18, 11, 19, - 5, 11, 8, 19, - 8, 5, 19, 4, - 8, 4, 19, 16, - }, - // 0b11010111 case 215 - { - 3, 2, 11, 19, - 3, 14, 2, 19, - 3, 12, 14, 19, - 12, 13, 14, 19, - 12, 13, 19, 16, - 13, 14, 16, 9, - 9, 14, 16, 4, - 14, 19, 16, 4, - 14, 4, 9, 5, - 14, 19, 4, 5, - 14, 19, 5, 18, - }, - // 0b11011000 case 216 - { - 2, 15, 3, 10, - 15, 3, 10, 8, - 10, 15, 8, 5, - 15, 8, 5, 4, - 15, 5, 10, 18, - 15, 8, 4, 16, - 15, 4, 5, 19, - 15, 16, 4, 19, - 15, 5, 18, 19, - }, - // 0b11011001 case 217 - { - 2, 12, 0, 4, - 2, 15, 12, 4, - 15, 12, 4, 16, - 2, 15, 16, 19, - 2, 19, 16, 4, - 2, 19, 4, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11011010 case 218 - { - 0, 13, 1, 9, - 2, 15, 3, 10, - 15, 3, 10, 8, - 10, 15, 8, 5, - 5, 15, 8, 4, - 15, 5, 10, 18, - 15, 4, 5, 19, - 15, 8, 4, 16, - 15, 5, 18, 19, - 15, 16, 4, 19, - }, - // 0b11011011 case 219 - { - 13, 1, 2, 9, - 12, 13, 2, 9, - 12, 2, 15, 9, - 15, 9, 2, 4, - 15, 12, 9, 4, - 15, 12, 4, 16, - 15, 16, 2, 19, - 2, 16, 4, 19, - 2, 19, 4, 5, - 2, 19, 5, 10, - 10, 19, 5, 18, - }, - // 0b11011100 case 220 - { - 1, 14, 3, 5, - 14, 15, 3, 5, - 14, 15, 5, 18, - 15, 3, 5, 8, - 15, 8, 5, 4, - 15, 8, 4, 16, - 15, 16, 4, 19, - 15, 4, 5, 19, - 15, 5, 18, 19, - }, - // 0b11011101 case 221 - { - 14, 0, 1, 5, - 14, 15, 0, 5, - 14, 15, 5, 18, - 15, 12, 0, 5, - 12, 0, 5, 4, - 15, 12, 18, 19, - 12, 4, 5, 16, - 12, 5, 18, 16, - 12, 18, 19, 16, - }, - // 0b11011110 case 222 - { - 13, 3, 0, 9, - 13, 14, 3, 9, - 14, 3, 9, 5, - 14, 3, 5, 18, - 14, 15, 3, 18, - 15, 3, 18, 19, - 3, 18, 19, 5, - 3, 5, 19, 4, - 3, 4, 19, 8, - 8, 4, 19, 16, - }, - // 0b11011111 case 223 - { - 14, 12, 13, 9, - 14, 15, 12, 9, - 14, 15, 9, 5, - 14, 15, 5, 18, - 15, 9, 5, 4, - 15, 12, 9, 4, - 15, 12, 4, 16, - 15, 16, 4, 19, - 15, 4, 5, 19, - 15, 5, 18, 19, - }, - // 0b11100000 case 224 - { - 9, 10, 11, 7, - 9, 10, 7, 4, - 10, 11, 7, 19, - 10, 4, 9, 17, - 10, 19, 7, 18, - 10, 7, 4, 18, - 10, 4, 17, 18, - }, - // 0b11100001 case 225 - { - 3, 12, 0, 8, - 9, 10, 11, 7, - 9, 10, 7, 4, - 10, 11, 7, 19, - 10, 4, 9, 17, - 10, 19, 7, 18, - 10, 7, 4, 18, - 10, 4, 17, 18, - }, - // 0b11100010 case 226 - { - 0, 13, 1, 4, - 13, 1, 4, 17, - 1, 4, 17, 10, - 10, 4, 17, 18, - 1, 4, 10, 11, - 10, 11, 4, 18, - 18, 11, 4, 7, - 18, 11, 7, 19, - }, - // 0b11100011 case 227 - { - 12, 1, 3, 4, - 12, 4, 3, 8, - 12, 13, 1, 4, - 13, 1, 4, 17, - 1, 4, 17, 10, - 10, 4, 17, 18, - 10, 11, 4, 18, - 11, 4, 18, 7, - 11, 7, 18, 19, - }, - // 0b11100100 case 228 - { - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 4, - 14, 11, 4, 7, - 14, 11, 7, 19, - 14, 4, 9, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - }, - // 0b11100101 case 229 - { - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 4, - 14, 11, 4, 7, - 14, 11, 7, 19, - 14, 4, 9, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - 3, 12, 0, 8, - }, - // 0b11100110 case 230 - { - 0, 13, 2, 4, - 13, 14, 2, 4, - 13, 14, 4, 17, - 14, 2, 17, 18, - 2, 4, 17, 18, - 2, 4, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11100111 case 231 - { - 12, 2, 3, 8, - 12, 13, 2, 8, - 13, 2, 8, 4, - 13, 14, 2, 4, - 13, 14, 4, 17, - 14, 2, 17, 18, - 2, 4, 17, 18, - 2, 4, 18, 7, - 2, 7, 18, 11, - 11, 7, 18, 19, - }, - // 0b11101000 case 232 - { - 2, 15, 3, 7, - 2, 15, 7, 19, - 2, 19, 7, 4, - 2, 19, 4, 9, - 9, 19, 4, 17, - 2, 19, 9, 10, - 9, 10, 19, 17, - 10, 19, 17, 18, - }, - // 0b11101001 case 233 - { - 2, 12, 0, 7, - 12, 0, 7, 8, - 2, 15, 12, 7, - 2, 15, 7, 19, - 2, 19, 7, 10, - 10, 19, 7, 18, - 9, 10, 7, 18, - 9, 18, 7, 4, - 9, 18, 4, 17, - }, - // 0b11101010 case 234 - { - 0, 13, 1, 10, - 0, 13, 10, 17, - 0, 17, 10, 4, - 10, 4, 17, 18, - 10, 7, 4, 18, - 2, 15, 3, 10, - 15, 3, 10, 7, - 10, 15, 7, 18, - 15, 7, 18, 19, - }, - // 0b11101011 case 235 - { - 13, 1, 2, 10, - 13, 2, 15, 10, - 13, 15, 12, 10, - 12, 13, 10, 18, - 10, 15, 12, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 8, - 12, 18, 19, 8, - 8, 17, 18, 4, - 8, 4, 18, 7, - 19, 8, 18, 7, - }, - // 0b11101100 case 236 - { - 1, 15, 3, 7, - 1, 14, 15, 7, - 14, 15, 7, 19, - 1, 14, 19, 18, - 1, 18, 19, 7, - 1, 18, 7, 4, - 1, 18, 4, 9, - 9, 18, 4, 17, - }, - // 0b11101101 case 237 - { - 1, 12, 0, 8, - 1, 15, 12, 8, - 1, 14, 15, 8, - 1, 14, 8, 7, - 14, 15, 8, 7, - 14, 15, 7, 19, - 1, 14, 19, 18, - 1, 18, 19, 7, - 1, 18, 7, 4, - 4, 1, 18, 9, - 9, 18, 4, 17, - }, - // 0b11101110 case 238 - { - 13, 3, 0, 4, - 13, 15, 3, 4, - 15, 3, 4, 7, - 13, 14, 15, 7, - 13, 14, 7, 4, - 14, 15, 7, 19, - 13, 14, 4, 17, - 14, 19, 7, 18, - 14, 7, 4, 18, - 14, 4, 17, 18, - }, - // 0b11101111 case 239 - { - 14, 15, 12, 18, - 12, 13, 14, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 8, - 12, 18, 19, 8, - 8, 17, 18, 4, - 18, 8, 4, 7, - 19, 8, 18, 7, - }, - // 0b11110000 case 240 - { - 9, 10, 11, 18, - 8, 9, 11, 18, - 8, 9, 18, 17, - 18, 11, 8, 19, - 8, 17, 18, 16, - 8, 18, 19, 16, - }, - // 0b11110001 case 241 - { - 3, 12, 0, 11, - 12, 0, 11, 9, - 11, 12, 9, 16, - 9, 10, 11, 16, - 10, 11, 16, 19, - 9, 10, 16, 17, - 10, 19, 16, 18, - 10, 16, 17, 18, - }, - // 0b11110010 case 242 - { - 0, 13, 1, 10, - 0, 13, 10, 8, - 8, 13, 10, 17, - 8, 17, 10, 18, - 8, 17, 18, 16, - 11, 8, 10, 16, - 11, 16, 10, 18, - 11, 16, 18, 19, - }, - // 0b11110011 case 243 - { - 12, 1, 3, 11, - 12, 13, 1, 11, - 13, 1, 11, 10, - 11, 13, 10, 18, - 11, 13, 18, 19, - 12, 13, 11, 19, - 12, 13, 18, 17, - 12, 17, 18, 19, - 12, 17, 19, 16, - }, - // 0b11110100 case 244 - { - 1, 14, 2, 11, - 1, 14, 11, 9, - 14, 11, 9, 18, - 11, 9, 18, 19, - 9, 18, 19, 17, - 8, 9, 11, 19, - 8, 9, 19, 17, - 8, 17, 19, 16, - }, - // 0b11110101 case 245 - { - 3, 12, 0, 11, - 12, 0, 11, 9, - 1, 14, 2, 9, - 14, 2, 9, 11, - 14, 11, 9, 18, - 12, 9, 11, 19, - 9, 18, 11, 19, - 12, 9, 19, 16, - 9, 18, 19, 17, - 9, 19, 16, 17, - }, - // 0b11110110 case 246 - { - 0, 13, 2, 8, - 13, 2, 8, 11, - 13, 14, 2, 11, - 13, 14, 11, 19, - 13, 11, 8, 19, - 13, 19, 8, 16, - 13, 14, 19, 18, - 13, 19, 16, 17, - 13, 18, 19, 17, - }, - // 0b11110111 case 247 - { - 12, 2, 3, 11, - 12, 14, 2, 11, - 12, 13, 14, 11, - 13, 14, 11, 18, - 12, 13, 11, 18, - 12, 18, 11, 19, - 12, 13, 18, 17, - 12, 18, 19, 16, - 12, 17, 18, 16, - }, - // 0b11111000 case 248 - { - 2, 15, 3, 10, - 15, 3, 10, 8, - 15, 8, 10, 19, - 8, 10, 19, 16, - 16, 10, 19, 18, - 8, 9, 10, 16, - 16, 9, 10, 18, - 9, 18, 16, 17, - }, - // 0b11111001 case 249 - { - 2, 15, 0, 10, - 15, 12, 0, 10, - 12, 0, 10, 9, - 10, 15, 9, 18, - 15, 12, 9, 18, - 12, 9, 18, 17, - 18, 15, 12, 19, - 12, 17, 18, 19, - 12, 17, 19, 16, - }, - // 0b11111010 case 250 - { - 0, 13, 1, 8, - 13, 1, 8, 10, - 8, 13, 10, 16, - 13, 10, 16, 18, - 13, 18, 16, 17, - 2, 15, 3, 10, - 15, 3, 10, 8, - 15, 8, 10, 18, - 15, 8, 18, 16, - 15, 16, 18, 19, - }, - // 0b11111011 case 251 - { - 2, 1, 10, 18, - 2, 15, 1, 18, - 15, 13, 1, 18, - 15, 12, 13, 18, - 15, 12, 18, 19, - 12, 13, 18, 17, - 12, 17, 18, 16, - 12, 18, 19, 16, - }, - // 0b11111100 case 252 - { - 1, 14, 3, 9, - 14, 3, 9, 8, - 14, 15, 3, 8, - 9, 14, 8, 17, - 14, 15, 8, 17, - 17, 15, 8, 16, - 14, 15, 17, 18, - 15, 17, 18, 19, - 15, 16, 17, 19, - }, - // 0b11111101 case 253 - { - 1, 0, 9, 17, - 14, 0, 1, 17, - 14, 12, 0, 17, - 14, 15, 12, 17, - 14, 15, 17, 18, - 15, 12, 17, 16, - 15, 17, 18, 19, - 15, 16, 17, 19, - }, - // 0b11111110 case 254 - { - 0, 3, 8, 16, - 13, 3, 0, 16, - 13, 15, 3, 16, - 13, 14, 15, 16, - 13, 14, 16, 17, - 14, 15, 16, 19, - 14, 16, 17, 18, - 14, 19, 16, 18, - }, - // 0b11111111 case 255 - { - 12, 14, 15, 19, - 12, 13, 14, 19, - 12, 13, 19, 16, - 13, 14, 19, 18, - 13, 18, 19, 17, - 13, 19, 16, 17, - }, -} - -//----------------------------------------------------------------------------- diff --git a/render/marchfelogic.go b/render/marchfelogic.go index e54e53843..dfee25d08 100644 --- a/render/marchfelogic.go +++ b/render/marchfelogic.go @@ -1,6 +1,7 @@ package render import ( + "github.com/Megidd/tetrahedron-table/src/gotable" "github.com/deadsy/sdfx/sdf" "github.com/deadsy/sdfx/vec/conv" v3 "github.com/deadsy/sdfx/vec/v3" @@ -243,7 +244,7 @@ func mcToTet4(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) } // Create the tetrahedra. - table := mcTetrahedronTable[index] + table := gotable.TetrahedronTable[index] count := len(table) / 4 result := make([]*sdf.Fe, 0, count) for i := 0; i < count; i++ { @@ -298,7 +299,7 @@ func mcToTet10(p [8]v3.Vec, v [8]float64, x float64, layerX, layerY, layerZ int) } // Create the tetrahedra. - table := mcTetrahedronTable[index] + table := gotable.TetrahedronTable[index] count := len(table) / 4 result := make([]*sdf.Fe, 0, count) for i := 0; i < count; i++ { From 7f1c5b31cd7794e97b207faa0930055993d8e266 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 12:39:49 +0330 Subject: [PATCH 718/775] Pass another arg --- examples/finite_elements/main.go | 6 ++++-- examples/finite_elements/main_test.go | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f0109334c..1458c058e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -59,7 +59,7 @@ type Load struct { // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - if len(os.Args) != 6 { + if len(os.Args) != 7 { log.Fatalf("usage: wrong argument count") } @@ -68,6 +68,7 @@ func main() { pthLoads := os.Args[3] pthRestraints := os.Args[4] pthResult := os.Args[5] + pthResultInfo := os.Args[6] jsonData, err := os.ReadFile(pthSpecs) if err != nil { @@ -102,7 +103,7 @@ func main() { log.Fatalf("%s", err) } - err = Run(pthStl, specs, restraints, loads, pthResult) + err = Run(pthStl, specs, restraints, loads, pthResult, pthResultInfo) if err != nil { log.Fatalf("%s", err) } @@ -114,6 +115,7 @@ func Run( restraints []Restraint, loads []Load, pthResult string, + pthResultInfo string, ) error { // create the SDF from the STL mesh inSdf, err := obj.ImportSTL(pthStl, 20, 3, 5) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 108f9e11c..7274031fe 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -29,6 +29,7 @@ func Test_main(t *testing.T) { pthLoads string // To be created by test. pthRestraints string // To be created by test. pthResult string // Result file, consumable by ABAQUS or CalculiX. + pthResultInfo string // Result details and info. specs Specs loads []Load // If load is zero, gravity would be the dominant force. restraints []Restraint @@ -41,6 +42,7 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "bms-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bms-restraints.json"), pthResult: filepath.Join(os.TempDir(), "bms-result.inp"), + pthResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), specs: Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -108,6 +110,7 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "bmc-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmc-restraints.json"), pthResult: filepath.Join(os.TempDir(), "bmc-result.inp"), + pthResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), specs: Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -154,6 +157,7 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "bmp-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmp-restraints.json"), pthResult: filepath.Join(os.TempDir(), "bmp-result.inp"), + pthResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), specs: Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -200,6 +204,7 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "bmi-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmi-restraints.json"), pthResult: filepath.Join(os.TempDir(), "bmi-result.inp"), + pthResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), specs: Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -252,6 +257,7 @@ func Test_main(t *testing.T) { pthLoads: filepath.Join(os.TempDir(), "teapot-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "teapot-restraints.json"), pthResult: filepath.Join(os.TempDir(), "teapot-result.inp"), + pthResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), specs: Specs{ MassDensity: 7.85e-9, YoungModulus: 210000, @@ -330,6 +336,7 @@ func Test_main(t *testing.T) { tt.pthLoads, tt.pthRestraints, tt.pthResult, + tt.pthResultInfo, } main() }) From ba7c24149169dd989e6d7723b3a370b65b2a7ea9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 12:53:02 +0330 Subject: [PATCH 719/775] Save result info JSON --- examples/finite_elements/main.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 1458c058e..ddd52b21b 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -11,7 +11,6 @@ package main import ( "encoding/json" - "fmt" "log" "os" @@ -55,6 +54,11 @@ type Load struct { MagZ float64 } +type ResultInfo struct { + ComponentCount int + Components []struct{ VoxelCount int } +} + // Render STL to SDF3 to finite elements. // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. @@ -141,9 +145,21 @@ func Run( m, _ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) components := m.Components() - fmt.Printf("components count: %v\n", len(components)) + ri := ResultInfo{ + ComponentCount: len(components), + Components: make([]struct{ VoxelCount int }, len(components)), + } for i, component := range components { - fmt.Printf("component %v voxel count: %v\n", i, component.VoxelCount()) + ri.Components[i] = struct{ VoxelCount int }{VoxelCount: component.VoxelCount()} + } + + jsonData, err := json.MarshalIndent(components, "", " ") + if err != nil { + log.Fatalf(err.Error()) + } + err = os.WriteFile(pthResultInfo, jsonData, 0644) + if err != nil { + log.Fatalf(err.Error()) } if specs.LayersAllConsidered { From 52469865443c724a16f09322dfe4175e57a8fc63 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 12:55:01 +0330 Subject: [PATCH 720/775] Error handling --- examples/finite_elements/main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index ddd52b21b..4959e365a 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -124,7 +124,7 @@ func Run( // create the SDF from the STL mesh inSdf, err := obj.ImportSTL(pthStl, 20, 3, 5) if err != nil { - log.Fatalf("%s", err) + return err } var order render.Order @@ -155,11 +155,11 @@ func Run( jsonData, err := json.MarshalIndent(components, "", " ") if err != nil { - log.Fatalf(err.Error()) + return err } err = os.WriteFile(pthResultInfo, jsonData, 0644) if err != nil { - log.Fatalf(err.Error()) + return err } if specs.LayersAllConsidered { From b68408987b91b700a13a89ef90b378e05aefcc43 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 12:55:53 +0330 Subject: [PATCH 721/775] Error handling --- examples/finite_elements/main.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 4959e365a..07ff26523 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -76,40 +76,40 @@ func main() { jsonData, err := os.ReadFile(pthSpecs) if err != nil { - log.Fatalf("%s", err) + log.Fatalf(err.Error()) } var specs Specs err = json.Unmarshal(jsonData, &specs) if err != nil { - log.Fatalf("%s", err) + log.Fatalf(err.Error()) } jsonData, err = os.ReadFile(pthLoads) if err != nil { - log.Fatalf("%s", err) + log.Fatalf(err.Error()) } var loads []Load err = json.Unmarshal(jsonData, &loads) if err != nil { - log.Fatalf("%s", err) + log.Fatalf(err.Error()) } jsonData, err = os.ReadFile(pthRestraints) if err != nil { - log.Fatalf("%s", err) + log.Fatalf(err.Error()) } var restraints []Restraint err = json.Unmarshal(jsonData, &restraints) if err != nil { - log.Fatalf("%s", err) + log.Fatalf(err.Error()) } err = Run(pthStl, specs, restraints, loads, pthResult, pthResultInfo) if err != nil { - log.Fatalf("%s", err) + log.Fatalf(err.Error()) } } From a72521d6aefb418cbdaf8a5766a776c26ee51718 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 13:19:14 +0330 Subject: [PATCH 722/775] Avoid anonymous type --- examples/finite_elements/main.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 07ff26523..ac0ce4ab5 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -54,9 +54,13 @@ type Load struct { MagZ float64 } +type Component struct { + VoxelCount int +} + type ResultInfo struct { ComponentCount int - Components []struct{ VoxelCount int } + Components []Component } // Render STL to SDF3 to finite elements. @@ -147,10 +151,10 @@ func Run( components := m.Components() ri := ResultInfo{ ComponentCount: len(components), - Components: make([]struct{ VoxelCount int }, len(components)), + Components: make([]Component, len(components)), } for i, component := range components { - ri.Components[i] = struct{ VoxelCount int }{VoxelCount: component.VoxelCount()} + ri.Components[i] = Component{VoxelCount: component.VoxelCount()} } jsonData, err := json.MarshalIndent(components, "", " ") From d580d3c1f1b77be3150e10e85e914611802e1f77 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 13:22:57 +0330 Subject: [PATCH 723/775] Fix bug --- examples/finite_elements/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index ac0ce4ab5..f98438d74 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -157,7 +157,7 @@ func Run( ri.Components[i] = Component{VoxelCount: component.VoxelCount()} } - jsonData, err := json.MarshalIndent(components, "", " ") + jsonData, err := json.MarshalIndent(ri, "", " ") if err != nil { return err } From f13c802f1e43e176d39b1e68714f53daed85f229 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 14:51:25 +0330 Subject: [PATCH 724/775] Modify read-me file --- examples/finite_elements/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 487cd6a1f..e01addcb8 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -6,15 +6,15 @@ Output is generated as `inp` files for ABAQUS or CalculiX. Nodes and elements ar ## Loading -The final `inp` file applies a distributed *weight* load to all elements. This load is calculated according to the material density. This load is in `+Z` direction. Assuming the 3D model will be 3D printed upside-down by SLA technology. +The final `inp` file applies a distributed *gravity* load to all elements. Additional point loads are defined by a JSON file. ## Boundary -In the final `inp` file, the boundary is defined by the first few layers at the bottom of the 3D model. Assuming the 3D model will be 3D printed upside-down by SLA technology. +In the final `inp` file, the boundary is defined by the point restraints inside a JSON file. ## Modification -Currently, no convenient ways are provided here for adjusting loading and boundary conditions. However, they may be developed and offered in the future. +Currently, a convenient way for adjusting loading and boundary conditions is provided. Simply modify the load and restraint JSON files. # CCX and CGX From fce8ef024faf6aff7a6fc1411312d85248107cfc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 14:53:31 +0330 Subject: [PATCH 725/775] Modify read-me --- examples/finite_elements/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index e01addcb8..30f6e7d06 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -14,7 +14,7 @@ In the final `inp` file, the boundary is defined by the point restraints inside ## Modification -Currently, a convenient way for adjusting loading and boundary conditions is provided. Simply modify the load and restraint JSON files. +Currently, a convenient way for making adjustments is provided. Simply modify the load, restraint, and specification JSON files. # CCX and CGX From bda8dbb3112775829cd55136dcf177f841359ab8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 2 Sep 2023 14:55:46 +0330 Subject: [PATCH 726/775] Update read-me --- examples/finite_elements/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 30f6e7d06..9bd8e7814 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -14,7 +14,7 @@ In the final `inp` file, the boundary is defined by the point restraints inside ## Modification -Currently, a convenient way for making adjustments is provided. Simply modify the load, restraint, and specification JSON files. +Currently, a convenient way for making adjustments is provided. Simply modify the load, restraint, and specification JSON files. Examining the unit tests is helpful to figure out how. # CCX and CGX From c9a25f853dc4f2782fc2664322146cc35d08b56c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 10:03:02 +0330 Subject: [PATCH 727/775] Change API: prepare for layer-by-layer --- examples/finite_elements/main.go | 27 ++++++++--------- examples/finite_elements/main_test.go | 42 ++++++++++++--------------- 2 files changed, 30 insertions(+), 39 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f98438d74..82a914a22 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -21,6 +21,9 @@ import ( ) type Specs struct { + PathStl string // Input STL file. + PathResult string // Result file, consumable by ABAQUS or CalculiX. + PathResultInfo string // Result details and info. MassDensity float64 YoungModulus float64 PoissonRatio float64 @@ -67,16 +70,13 @@ type ResultInfo struct { // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - if len(os.Args) != 7 { + if len(os.Args) != 4 { log.Fatalf("usage: wrong argument count") } - pthStl := os.Args[1] - pthSpecs := os.Args[2] - pthLoads := os.Args[3] - pthRestraints := os.Args[4] - pthResult := os.Args[5] - pthResultInfo := os.Args[6] + pthSpecs := os.Args[1] + pthLoads := os.Args[2] + pthRestraints := os.Args[3] jsonData, err := os.ReadFile(pthSpecs) if err != nil { @@ -111,22 +111,19 @@ func main() { log.Fatalf(err.Error()) } - err = Run(pthStl, specs, restraints, loads, pthResult, pthResultInfo) + err = Run(specs, restraints, loads) if err != nil { log.Fatalf(err.Error()) } } func Run( - pthStl string, specs Specs, restraints []Restraint, loads []Load, - pthResult string, - pthResultInfo string, ) error { // create the SDF from the STL mesh - inSdf, err := obj.ImportSTL(pthStl, 20, 3, 5) + inSdf, err := obj.ImportSTL(specs.PathStl, 20, 3, 5) if err != nil { return err } @@ -161,14 +158,14 @@ func Run( if err != nil { return err } - err = os.WriteFile(pthResultInfo, jsonData, 0644) + err = os.WriteFile(specs.PathResultInfo, jsonData, 0644) if err != nil { return err } if specs.LayersAllConsidered { // Write all layers of mesh to file. - return m.WriteInp(pthResult, + return m.WriteInp(specs.PathResult, float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), restraintsConvert(restraints), loadsConvert(loads), @@ -180,7 +177,7 @@ func Run( // Only from a start layer to an end layer along the Z axis. // Applicable to 3D print analysis that is done layer-by-layer. return m.WriteInpLayers( - pthResult, + specs.PathResult, specs.LayerStart, specs.LayerEnd, float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), restraintsConvert(restraints), diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 7274031fe..ec218cba9 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -24,12 +24,9 @@ func Test_main(t *testing.T) { tests := []struct { skip bool name string - pthStl string // Input STL file. - pthSpecs string // To be created by test. - pthLoads string // To be created by test. - pthRestraints string // To be created by test. - pthResult string // Result file, consumable by ABAQUS or CalculiX. - pthResultInfo string // Result details and info. + pthSpecs string // File to be created by test. + pthLoads string // File to be created by test. + pthRestraints string // File to be created by test. specs Specs loads []Load // If load is zero, gravity would be the dominant force. restraints []Restraint @@ -37,13 +34,13 @@ func Test_main(t *testing.T) { { skip: false, name: "benchmarkSquare", - pthStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), pthSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), pthLoads: filepath.Join(os.TempDir(), "bms-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bms-restraints.json"), - pthResult: filepath.Join(os.TempDir(), "bms-result.inp"), - pthResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), + PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -105,13 +102,13 @@ func Test_main(t *testing.T) { { skip: false, name: "benchmarkCircle", - pthStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), pthSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), pthLoads: filepath.Join(os.TempDir(), "bmc-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmc-restraints.json"), - pthResult: filepath.Join(os.TempDir(), "bmc-result.inp"), - pthResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), + PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -152,13 +149,13 @@ func Test_main(t *testing.T) { { skip: false, name: "benchmarkPipe", - pthStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), pthSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), pthLoads: filepath.Join(os.TempDir(), "bmp-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmp-restraints.json"), - pthResult: filepath.Join(os.TempDir(), "bmp-result.inp"), - pthResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), + PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -199,13 +196,13 @@ func Test_main(t *testing.T) { { skip: false, name: "benchmarkI", - pthStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), pthSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), pthLoads: filepath.Join(os.TempDir(), "bmi-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "bmi-restraints.json"), - pthResult: filepath.Join(os.TempDir(), "bmi-result.inp"), - pthResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), + PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -252,13 +249,13 @@ func Test_main(t *testing.T) { { skip: false, name: "teapot", - pthStl: filepath.Join("..", "..", "files", "teapot.stl"), pthSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), pthLoads: filepath.Join(os.TempDir(), "teapot-loads.json"), pthRestraints: filepath.Join(os.TempDir(), "teapot-restraints.json"), - pthResult: filepath.Join(os.TempDir(), "teapot-result.inp"), - pthResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "teapot.stl"), + PathResult: filepath.Join(os.TempDir(), "teapot-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -331,12 +328,9 @@ func Test_main(t *testing.T) { os.Args = []string{ "executable-name-dummy", - tt.pthStl, tt.pthSpecs, tt.pthLoads, tt.pthRestraints, - tt.pthResult, - tt.pthResultInfo, } main() }) From 4e350fc4ea651039da0edeeabe0502f636d8abd9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 10:21:19 +0330 Subject: [PATCH 728/775] Only one arg is passed: specs --- examples/finite_elements/main.go | 10 ++-- examples/finite_elements/main_test.go | 70 +++++++++++++-------------- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 82a914a22..35eb84ea1 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -22,6 +22,8 @@ import ( type Specs struct { PathStl string // Input STL file. + PathLoadPoints string // File containing point loads. + PathRestraintPoints string // File containing point restraints. PathResult string // Result file, consumable by ABAQUS or CalculiX. PathResultInfo string // Result details and info. MassDensity float64 @@ -70,13 +72,11 @@ type ResultInfo struct { // Write finite elements to an `inp` file. // Written file can be used by ABAQUS or CalculiX. func main() { - if len(os.Args) != 4 { + if len(os.Args) != 2 { log.Fatalf("usage: wrong argument count") } pthSpecs := os.Args[1] - pthLoads := os.Args[2] - pthRestraints := os.Args[3] jsonData, err := os.ReadFile(pthSpecs) if err != nil { @@ -89,7 +89,7 @@ func main() { log.Fatalf(err.Error()) } - jsonData, err = os.ReadFile(pthLoads) + jsonData, err = os.ReadFile(specs.PathLoadPoints) if err != nil { log.Fatalf(err.Error()) } @@ -100,7 +100,7 @@ func main() { log.Fatalf(err.Error()) } - jsonData, err = os.ReadFile(pthRestraints) + jsonData, err = os.ReadFile(specs.PathRestraintPoints) if err != nil { log.Fatalf(err.Error()) } diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index ec218cba9..31ec7d87e 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -22,23 +22,21 @@ import ( // https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections func Test_main(t *testing.T) { tests := []struct { - skip bool - name string - pthSpecs string // File to be created by test. - pthLoads string // File to be created by test. - pthRestraints string // File to be created by test. - specs Specs - loads []Load // If load is zero, gravity would be the dominant force. - restraints []Restraint + skip bool + name string + pthSpecs string // File to be created by test. + specs Specs + loads []Load // If load is zero, gravity would be the dominant force. + restraints []Restraint }{ { - skip: false, - name: "benchmarkSquare", - pthSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), - pthLoads: filepath.Join(os.TempDir(), "bms-loads.json"), - pthRestraints: filepath.Join(os.TempDir(), "bms-restraints.json"), + skip: false, + name: "benchmarkSquare", + pthSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), MassDensity: 7.85e-9, @@ -100,13 +98,13 @@ func Test_main(t *testing.T) { }(), }, { - skip: false, - name: "benchmarkCircle", - pthSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), - pthLoads: filepath.Join(os.TempDir(), "bmc-loads.json"), - pthRestraints: filepath.Join(os.TempDir(), "bmc-restraints.json"), + skip: false, + name: "benchmarkCircle", + pthSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), MassDensity: 7.85e-9, @@ -147,13 +145,13 @@ func Test_main(t *testing.T) { }, }, { - skip: false, - name: "benchmarkPipe", - pthSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), - pthLoads: filepath.Join(os.TempDir(), "bmp-loads.json"), - pthRestraints: filepath.Join(os.TempDir(), "bmp-restraints.json"), + skip: false, + name: "benchmarkPipe", + pthSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), MassDensity: 7.85e-9, @@ -194,13 +192,13 @@ func Test_main(t *testing.T) { }, }, { - skip: false, - name: "benchmarkI", - pthSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), - pthLoads: filepath.Join(os.TempDir(), "bmi-loads.json"), - pthRestraints: filepath.Join(os.TempDir(), "bmi-restraints.json"), + skip: false, + name: "benchmarkI", + pthSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), MassDensity: 7.85e-9, @@ -247,13 +245,13 @@ func Test_main(t *testing.T) { }(), }, { - skip: false, - name: "teapot", - pthSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), - pthLoads: filepath.Join(os.TempDir(), "teapot-loads.json"), - pthRestraints: filepath.Join(os.TempDir(), "teapot-restraints.json"), + skip: false, + name: "teapot", + pthSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "teapot.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "teapot-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "teapot-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "teapot-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), MassDensity: 7.85e-9, @@ -308,7 +306,7 @@ func Test_main(t *testing.T) { return } - err = os.WriteFile(tt.pthLoads, jsonData, 0644) + err = os.WriteFile(tt.specs.PathLoadPoints, jsonData, 0644) if err != nil { t.Error(err) return @@ -320,7 +318,7 @@ func Test_main(t *testing.T) { return } - err = os.WriteFile(tt.pthRestraints, jsonData, 0644) + err = os.WriteFile(tt.specs.PathRestraintPoints, jsonData, 0644) if err != nil { t.Error(err) return @@ -329,8 +327,6 @@ func Test_main(t *testing.T) { os.Args = []string{ "executable-name-dummy", tt.pthSpecs, - tt.pthLoads, - tt.pthRestraints, } main() }) From 88cd06609a29b54b31500c0514c4e29ce2bd617a Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 10:25:08 +0330 Subject: [PATCH 729/775] Rename --- examples/finite_elements/main_test.go | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 31ec7d87e..feb207161 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -24,15 +24,15 @@ func Test_main(t *testing.T) { tests := []struct { skip bool name string - pthSpecs string // File to be created by test. + pathSpecs string // File to be created by test. specs Specs loads []Load // If load is zero, gravity would be the dominant force. restraints []Restraint }{ { - skip: false, - name: "benchmarkSquare", - pthSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), + skip: false, + name: "benchmarkSquare", + pathSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), @@ -98,9 +98,9 @@ func Test_main(t *testing.T) { }(), }, { - skip: false, - name: "benchmarkCircle", - pthSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), + skip: false, + name: "benchmarkCircle", + pathSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), @@ -145,9 +145,9 @@ func Test_main(t *testing.T) { }, }, { - skip: false, - name: "benchmarkPipe", - pthSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), + skip: false, + name: "benchmarkPipe", + pathSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), @@ -192,9 +192,9 @@ func Test_main(t *testing.T) { }, }, { - skip: false, - name: "benchmarkI", - pthSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), + skip: false, + name: "benchmarkI", + pathSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), @@ -245,9 +245,9 @@ func Test_main(t *testing.T) { }(), }, { - skip: false, - name: "teapot", - pthSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), + skip: false, + name: "teapot", + pathSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), specs: Specs{ PathStl: filepath.Join("..", "..", "files", "teapot.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "teapot-load-points.json"), @@ -294,7 +294,7 @@ func Test_main(t *testing.T) { t.Error(err) return } - err = os.WriteFile(tt.pthSpecs, jsonData, 0644) + err = os.WriteFile(tt.pathSpecs, jsonData, 0644) if err != nil { t.Error(err) return @@ -326,7 +326,7 @@ func Test_main(t *testing.T) { os.Args = []string{ "executable-name-dummy", - tt.pthSpecs, + tt.pathSpecs, } main() }) From c1d803985b88ff3863cd09779662bf6105878acf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 11:11:21 +0330 Subject: [PATCH 730/775] Result info contains layer count --- examples/finite_elements/main.go | 8 +++++++- sdf/finiteelements/mesh/fem.go | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 35eb84ea1..75069b759 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -64,6 +64,9 @@ type Component struct { } type ResultInfo struct { + LayersX int + LayersY int + LayersZ int ComponentCount int Components []Component } @@ -143,10 +146,13 @@ func Run( } // Create a mesh of finite elements. - m, _ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) + m, layersX, layersY, layersZ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) components := m.Components() ri := ResultInfo{ + LayersX: layersX, + LayersY: layersY, + LayersZ: layersZ, ComponentCount: len(components), Components: make([]Component, len(components)), } diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 4f4cabc2d..5966ef612 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -21,8 +21,8 @@ type Fem struct { VBuff *buffer.VB } -// NewFem returns a new mesh and number of its layers along Z-axis. -func NewFem(s sdf.SDF3, r render.RenderFe) (*Fem, int) { +// NewFem returns a new mesh and number of its voxel layers along X, Y, Z axis. +func NewFem(s sdf.SDF3, r render.RenderFe) (*Fem, int, int, int) { fes := render.ToFem(s, r) voxelLen, voxelDim, mins, maxs := r.Voxels(s) @@ -36,7 +36,7 @@ func NewFem(s sdf.SDF3, r render.RenderFe) (*Fem, int) { defer m.VBuff.DestroyHashTable() - return m, voxelLen.Z + return m, voxelLen.X, voxelLen.Y, voxelLen.Z } func newFem(voxelLen v3i.Vec, voxelDim v3.Vec, mins, maxs []v3.Vec) *Fem { From 5afb33e0aadfd3a773a2a162e540058ae6686662 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 11:15:08 +0330 Subject: [PATCH 731/775] Rename --- examples/finite_elements/main.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 75069b759..6034e3528 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -64,9 +64,9 @@ type Component struct { } type ResultInfo struct { - LayersX int - LayersY int - LayersZ int + VoxelsX int + VoxelsY int + VoxelsZ int ComponentCount int Components []Component } @@ -146,13 +146,13 @@ func Run( } // Create a mesh of finite elements. - m, layersX, layersY, layersZ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) + m, voxelsX, voxelsY, voxelsZ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) components := m.Components() ri := ResultInfo{ - LayersX: layersX, - LayersY: layersY, - LayersZ: layersZ, + VoxelsX: voxelsX, + VoxelsY: voxelsY, + VoxelsZ: voxelsZ, ComponentCount: len(components), Components: make([]Component, len(components)), } From a47f93f16d6649fbbd4d2b8e2b1dd45f156e20bb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 11:49:59 +0330 Subject: [PATCH 732/775] Layer by layer result --- examples/finite_elements/main.go | 75 ++++++----- examples/finite_elements/main_test.go | 175 +++++++++++++------------- 2 files changed, 129 insertions(+), 121 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 6034e3528..b30c674e9 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -11,8 +11,10 @@ package main import ( "encoding/json" + "fmt" "log" "os" + "strings" "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" @@ -21,24 +23,23 @@ import ( ) type Specs struct { - PathStl string // Input STL file. - PathLoadPoints string // File containing point loads. - PathRestraintPoints string // File containing point restraints. - PathResult string // Result file, consumable by ABAQUS or CalculiX. - PathResultInfo string // Result details and info. - MassDensity float64 - YoungModulus float64 - PoissonRatio float64 - GravityDirectionX float64 - GravityDirectionY float64 - GravityDirectionZ float64 - GravityMagnitude float64 - Resolution int // Number of voxels on the longest axis of 3D model AABB. - LayersAllConsidered bool // If true, layer start and layer end are ignored. - LayerStart int - LayerEnd int - NonlinearConsidered bool // If true, nonlinear finite elements are generated. - ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. + PathStl string // Input STL file. + PathLoadPoints string // File containing point loads. + PathRestraintPoints string // File containing point restraints. + PathResult string // Result file, consumable by ABAQUS or CalculiX. + PathResultInfo string // Result details and info. + MassDensity float64 + YoungModulus float64 + PoissonRatio float64 + GravityDirectionX float64 + GravityDirectionY float64 + GravityDirectionZ float64 + GravityMagnitude float64 + Resolution int // Number of voxels on the longest axis of 3D model AABB. + LayerByLayerfor3dPrintAnalysis bool // If true, multiple results will be created layer-by-layer to simulated 3D print process. + PathResultLayerByLayer string // Only relevant if layer-by-layer is true. Must include "#" character as placeholder for layer number. + NonlinearConsidered bool // If true, nonlinear finite elements are generated. + ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. } type Restraint struct { @@ -169,7 +170,7 @@ func Run( return err } - if specs.LayersAllConsidered { + if !specs.LayerByLayerfor3dPrintAnalysis { // Write all layers of mesh to file. return m.WriteInp(specs.PathResult, float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), @@ -178,19 +179,31 @@ func Run( v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, ) } else { - // Write just some layers of mesh to file. - // Generate finite elements. - // Only from a start layer to an end layer along the Z axis. + // Write layer by layer. + // From first layer to the last layer along the Z axis. // Applicable to 3D print analysis that is done layer-by-layer. - return m.WriteInpLayers( - specs.PathResult, - specs.LayerStart, specs.LayerEnd, - float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), - restraintsConvert(restraints), - loadsConvert(loads), - v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, - ) - } + + if voxelsZ < 8 { + return fmt.Errorf("not enough voxel layers along the Z axis %d", voxelsZ) + } + + // The first few layers are ignored. + for z := 3; z < voxelsZ; z++ { + err = m.WriteInpLayers( + strings.Replace(specs.PathResultLayerByLayer, "#", fmt.Sprintf("%d", z), 1), + 0, z, + float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), + restraintsConvert(restraints), + loadsConvert(loads), + v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + ) + if err != nil { + return err + } + } + } + + return nil } func restraintsConvert(rs []Restraint) []*mesh.Restraint { diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index feb207161..f7117db48 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -34,24 +34,23 @@ func Test_main(t *testing.T) { name: "benchmarkSquare", pathSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: false, + PathResultLayerByLayer: "", + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { @@ -102,24 +101,23 @@ func Test_main(t *testing.T) { name: "benchmarkCircle", pathSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: false, + PathResultLayerByLayer: "", + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { @@ -149,24 +147,23 @@ func Test_main(t *testing.T) { name: "benchmarkPipe", pathSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: false, + PathResultLayerByLayer: "", + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { @@ -196,24 +193,23 @@ func Test_main(t *testing.T) { name: "benchmarkI", pathSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: false, + PathResultLayerByLayer: "", + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { @@ -249,24 +245,23 @@ func Test_main(t *testing.T) { name: "teapot", pathSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "teapot.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "teapot-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "teapot-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "teapot-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayersAllConsidered: true, - LayerStart: -1, // Negative means all layers. - LayerEnd: -1, // Negative means all layers. - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "teapot.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "teapot-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "teapot-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "teapot-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: true, + PathResultLayerByLayer: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { From 9ea75881461c5f564c4b1a0a7361ec9d3d8aece5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 14:36:34 +0330 Subject: [PATCH 733/775] Rename --- examples/finite_elements/main.go | 4 ++-- examples/finite_elements/main_test.go | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index b30c674e9..5ec392637 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -37,7 +37,7 @@ type Specs struct { GravityMagnitude float64 Resolution int // Number of voxels on the longest axis of 3D model AABB. LayerByLayerfor3dPrintAnalysis bool // If true, multiple results will be created layer-by-layer to simulated 3D print process. - PathResultLayerByLayer string // Only relevant if layer-by-layer is true. Must include "#" character as placeholder for layer number. + LayerByLayerPathResult string // Only relevant if layer-by-layer is true. Must include "#" character as placeholder for layer number. NonlinearConsidered bool // If true, nonlinear finite elements are generated. ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. } @@ -190,7 +190,7 @@ func Run( // The first few layers are ignored. for z := 3; z < voxelsZ; z++ { err = m.WriteInpLayers( - strings.Replace(specs.PathResultLayerByLayer, "#", fmt.Sprintf("%d", z), 1), + strings.Replace(specs.LayerByLayerPathResult, "#", fmt.Sprintf("%d", z), 1), 0, z, float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), restraintsConvert(restraints), diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index f7117db48..5635867ce 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -48,7 +48,7 @@ func Test_main(t *testing.T) { GravityMagnitude: 9810, Resolution: 50, LayerByLayerfor3dPrintAnalysis: false, - PathResultLayerByLayer: "", + LayerByLayerPathResult: "", NonlinearConsidered: false, ExactSurfaceConsidered: true, }, @@ -115,7 +115,7 @@ func Test_main(t *testing.T) { GravityMagnitude: 9810, Resolution: 50, LayerByLayerfor3dPrintAnalysis: false, - PathResultLayerByLayer: "", + LayerByLayerPathResult: "", NonlinearConsidered: false, ExactSurfaceConsidered: true, }, @@ -161,7 +161,7 @@ func Test_main(t *testing.T) { GravityMagnitude: 9810, Resolution: 50, LayerByLayerfor3dPrintAnalysis: false, - PathResultLayerByLayer: "", + LayerByLayerPathResult: "", NonlinearConsidered: false, ExactSurfaceConsidered: true, }, @@ -207,7 +207,7 @@ func Test_main(t *testing.T) { GravityMagnitude: 9810, Resolution: 50, LayerByLayerfor3dPrintAnalysis: false, - PathResultLayerByLayer: "", + LayerByLayerPathResult: "", NonlinearConsidered: false, ExactSurfaceConsidered: true, }, @@ -259,7 +259,7 @@ func Test_main(t *testing.T) { GravityMagnitude: 9810, Resolution: 50, LayerByLayerfor3dPrintAnalysis: true, - PathResultLayerByLayer: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), + LayerByLayerPathResult: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), NonlinearConsidered: false, ExactSurfaceConsidered: true, }, From 08f77268fe95bbb3ccfbcb54e06f3c2e25ad63b0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 15:19:16 +0330 Subject: [PATCH 734/775] Log --- examples/finite_elements/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 5ec392637..e7525fdac 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -200,6 +200,7 @@ func Run( if err != nil { return err } + fmt.Printf("Finite elements are generated from layer 0 to layer %v out of %v total.\n", z, voxelsZ-1) } } From 82164eb6ff03c7977e8b3f7495dc705d4a7752f4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 15:30:20 +0330 Subject: [PATCH 735/775] TODO: 3D print restraint --- examples/finite_elements/main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index e7525fdac..044243247 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -224,3 +224,6 @@ func loadsConvert(ls []Load) []*mesh.Load { } return loads } + +// TODO: For 3D print analysis, all the voxels at the same Z layer are considered as restraint. +// Since, the 3D print floor is at the same Z level. From 86b09059788ecc93fc1c1ea9546525393402331c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 15:57:07 +0330 Subject: [PATCH 736/775] Simplify --- examples/finite_elements/main.go | 79 ++++++++++++++++---------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 044243247..0ac546e7f 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -115,21 +115,10 @@ func main() { log.Fatalf(err.Error()) } - err = Run(specs, restraints, loads) - if err != nil { - log.Fatalf(err.Error()) - } -} - -func Run( - specs Specs, - restraints []Restraint, - loads []Load, -) error { // create the SDF from the STL mesh inSdf, err := obj.ImportSTL(specs.PathStl, 20, 3, 5) if err != nil { - return err + log.Fatalf(err.Error()) } var order render.Order @@ -150,7 +139,7 @@ func Run( m, voxelsX, voxelsY, voxelsZ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) components := m.Components() - ri := ResultInfo{ + info := ResultInfo{ VoxelsX: voxelsX, VoxelsY: voxelsY, VoxelsZ: voxelsZ, @@ -158,50 +147,62 @@ func Run( Components: make([]Component, len(components)), } for i, component := range components { - ri.Components[i] = Component{VoxelCount: component.VoxelCount()} + info.Components[i] = Component{VoxelCount: component.VoxelCount()} } - jsonData, err := json.MarshalIndent(ri, "", " ") + jsonData, err = json.MarshalIndent(info, "", " ") if err != nil { - return err + log.Fatalf(err.Error()) } err = os.WriteFile(specs.PathResultInfo, jsonData, 0644) if err != nil { - return err + log.Fatalf(err.Error()) } if !specs.LayerByLayerfor3dPrintAnalysis { - // Write all layers of mesh to file. - return m.WriteInp(specs.PathResult, + // Generate finite elements for all layers of mesh. + err = m.WriteInp( + specs.PathResult, float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), restraintsConvert(restraints), loadsConvert(loads), v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, ) } else { - // Write layer by layer. - // From first layer to the last layer along the Z axis. - // Applicable to 3D print analysis that is done layer-by-layer. + err = LayerByLayer(specs, restraints, loads, m, voxelsZ) + } + if err != nil { + log.Fatalf(err.Error()) + } +} - if voxelsZ < 8 { - return fmt.Errorf("not enough voxel layers along the Z axis %d", voxelsZ) - } +// Generate finite elements layer-by-layer. +// Applicable to 3D print analysis that is done layer-by-layer. +func LayerByLayer( + specs Specs, + restraints []Restraint, + loads []Load, + m *mesh.Fem, + voxelsZ int, +) error { + if voxelsZ < 8 { + return fmt.Errorf("not enough voxel layers along the Z axis %d", voxelsZ) + } - // The first few layers are ignored. - for z := 3; z < voxelsZ; z++ { - err = m.WriteInpLayers( - strings.Replace(specs.LayerByLayerPathResult, "#", fmt.Sprintf("%d", z), 1), - 0, z, - float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), - restraintsConvert(restraints), - loadsConvert(loads), - v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, - ) - if err != nil { - return err - } - fmt.Printf("Finite elements are generated from layer 0 to layer %v out of %v total.\n", z, voxelsZ-1) + // The first few layers are ignored. + for z := 3; z < voxelsZ; z++ { + err := m.WriteInpLayers( + strings.Replace(specs.LayerByLayerPathResult, "#", fmt.Sprintf("%d", z), 1), + 0, z, + float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), + restraintsConvert(restraints), + loadsConvert(loads), + v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + ) + if err != nil { + return err } + fmt.Printf("Finite elements are generated from layer 0 to layer %v out of %v total.\n", z, voxelsZ-1) } return nil From a4c26ffa3921ef62eccb50cfd60822834599878d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 16:59:15 +0330 Subject: [PATCH 737/775] Copy over another example --- examples/finite_elements_print3d/README.md | 76 ++++ examples/finite_elements_print3d/main.go | 230 ++++++++++++ examples/finite_elements_print3d/main_test.go | 329 ++++++++++++++++++ 3 files changed, 635 insertions(+) create mode 100644 examples/finite_elements_print3d/README.md create mode 100644 examples/finite_elements_print3d/main.go create mode 100644 examples/finite_elements_print3d/main_test.go diff --git a/examples/finite_elements_print3d/README.md b/examples/finite_elements_print3d/README.md new file mode 100644 index 000000000..9bd8e7814 --- /dev/null +++ b/examples/finite_elements_print3d/README.md @@ -0,0 +1,76 @@ +# Output + +## Nodes and elements + +Output is generated as `inp` files for ABAQUS or CalculiX. Nodes and elements are saved in separate files, which are then included inside a single, final `inp` file. This final `inp` file can be opened and viewed using [FreeCAD](https://en.wikipedia.org/wiki/FreeCAD). + +## Loading + +The final `inp` file applies a distributed *gravity* load to all elements. Additional point loads are defined by a JSON file. + +## Boundary + +In the final `inp` file, the boundary is defined by the point restraints inside a JSON file. + +## Modification + +Currently, a convenient way for making adjustments is provided. Simply modify the load, restraint, and specification JSON files. Examining the unit tests is helpful to figure out how. + +# CCX and CGX + +The results can be consumed by ABAQUS or CalculiX. + +CalculiX and CalculiX GraphiX binaries are available for different platforms, like Linux distributions. + +## openSUSE + +openSUSE has [CCX](https://software.opensuse.org/package/ccx) package and also [CGX](https://software.opensuse.org/package/cgx) one. + +To install CCX and CGX on openSUSE Leap 15.5 you can run as root: + +```bash +zypper addrepo https://download.opensuse.org/repositories/science/15.5/science.repo +zypper refresh +zypper install ccx +zypper install cgx +``` + +# Visualize `inp` file + +To visualize the `inp` file by CalculiX GraphiX: + +```bash +cgx -c hex8.inp +``` + +# Analyze `inp` file + +To run the `inp` files by FEA engines like CalculiX: + +```bash +ccx -i hex8 +``` + +The above `-i` flag expects a `hex8.inp` file. + +The above command creates `frd` files containing the results. They can be viewed by CalculiX GraphiX: + +```bash +cgx hex8.frd +``` + +The boundary conditions and loads used in the calculation will be available together with the results if you run: + +```bash +cgx hex8.frd hex8.inp +``` + +## Math solver + +The default CCX math solver is `SPOOLES` which is slow. Apparently `PARDISO` is faster and `PaStiX` is the fastest. But it's needed to build the CCX with `PARDISO` or `PaStiX` math libraries. + +### PARDISO + +#### Linux executable with the Intel Pardiso Solver + +You can download [here](https://www.dropbox.com/s/x8axi53l9dk9w4g/ccx_2.19_MT?dl=1) an executable with the Intel Pardiso solver for x86_64 Linux systems. The executable has all the libraries statically linked into it. So it should run by itself without any dependency. Thanks to [these guys](https://www.feacluster.com/calculix.php). diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go new file mode 100644 index 000000000..0ac546e7f --- /dev/null +++ b/examples/finite_elements_print3d/main.go @@ -0,0 +1,230 @@ +//----------------------------------------------------------------------------- +/* + +Finite elements from triangle mesh. +The result `inp` file is consumable by ABAQUS or CalculiX. + +*/ +//----------------------------------------------------------------------------- + +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + "strings" + + "github.com/deadsy/sdfx/obj" + "github.com/deadsy/sdfx/render" + "github.com/deadsy/sdfx/sdf/finiteelements/mesh" + v3 "github.com/deadsy/sdfx/vec/v3" +) + +type Specs struct { + PathStl string // Input STL file. + PathLoadPoints string // File containing point loads. + PathRestraintPoints string // File containing point restraints. + PathResult string // Result file, consumable by ABAQUS or CalculiX. + PathResultInfo string // Result details and info. + MassDensity float64 + YoungModulus float64 + PoissonRatio float64 + GravityDirectionX float64 + GravityDirectionY float64 + GravityDirectionZ float64 + GravityMagnitude float64 + Resolution int // Number of voxels on the longest axis of 3D model AABB. + LayerByLayerfor3dPrintAnalysis bool // If true, multiple results will be created layer-by-layer to simulated 3D print process. + LayerByLayerPathResult string // Only relevant if layer-by-layer is true. Must include "#" character as placeholder for layer number. + NonlinearConsidered bool // If true, nonlinear finite elements are generated. + ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. +} + +type Restraint struct { + LocX float64 + LocY float64 + LocZ float64 + IsFixedX bool + IsFixedY bool + IsFixedZ bool +} + +type Load struct { + LocX float64 + LocY float64 + LocZ float64 + MagX float64 + MagY float64 + MagZ float64 +} + +type Component struct { + VoxelCount int +} + +type ResultInfo struct { + VoxelsX int + VoxelsY int + VoxelsZ int + ComponentCount int + Components []Component +} + +// Render STL to SDF3 to finite elements. +// Write finite elements to an `inp` file. +// Written file can be used by ABAQUS or CalculiX. +func main() { + if len(os.Args) != 2 { + log.Fatalf("usage: wrong argument count") + } + + pthSpecs := os.Args[1] + + jsonData, err := os.ReadFile(pthSpecs) + if err != nil { + log.Fatalf(err.Error()) + } + + var specs Specs + err = json.Unmarshal(jsonData, &specs) + if err != nil { + log.Fatalf(err.Error()) + } + + jsonData, err = os.ReadFile(specs.PathLoadPoints) + if err != nil { + log.Fatalf(err.Error()) + } + + var loads []Load + err = json.Unmarshal(jsonData, &loads) + if err != nil { + log.Fatalf(err.Error()) + } + + jsonData, err = os.ReadFile(specs.PathRestraintPoints) + if err != nil { + log.Fatalf(err.Error()) + } + + var restraints []Restraint + err = json.Unmarshal(jsonData, &restraints) + if err != nil { + log.Fatalf(err.Error()) + } + + // create the SDF from the STL mesh + inSdf, err := obj.ImportSTL(specs.PathStl, 20, 3, 5) + if err != nil { + log.Fatalf(err.Error()) + } + + var order render.Order + if specs.NonlinearConsidered { + order = render.Quadratic + } else { + order = render.Linear + } + + var shape render.Shape + if specs.ExactSurfaceConsidered { + shape = render.HexAndTet + } else { + shape = render.Hexahedral + } + + // Create a mesh of finite elements. + m, voxelsX, voxelsY, voxelsZ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) + + components := m.Components() + info := ResultInfo{ + VoxelsX: voxelsX, + VoxelsY: voxelsY, + VoxelsZ: voxelsZ, + ComponentCount: len(components), + Components: make([]Component, len(components)), + } + for i, component := range components { + info.Components[i] = Component{VoxelCount: component.VoxelCount()} + } + + jsonData, err = json.MarshalIndent(info, "", " ") + if err != nil { + log.Fatalf(err.Error()) + } + err = os.WriteFile(specs.PathResultInfo, jsonData, 0644) + if err != nil { + log.Fatalf(err.Error()) + } + + if !specs.LayerByLayerfor3dPrintAnalysis { + // Generate finite elements for all layers of mesh. + err = m.WriteInp( + specs.PathResult, + float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), + restraintsConvert(restraints), + loadsConvert(loads), + v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + ) + } else { + err = LayerByLayer(specs, restraints, loads, m, voxelsZ) + } + if err != nil { + log.Fatalf(err.Error()) + } +} + +// Generate finite elements layer-by-layer. +// Applicable to 3D print analysis that is done layer-by-layer. +func LayerByLayer( + specs Specs, + restraints []Restraint, + loads []Load, + m *mesh.Fem, + voxelsZ int, +) error { + if voxelsZ < 8 { + return fmt.Errorf("not enough voxel layers along the Z axis %d", voxelsZ) + } + + // The first few layers are ignored. + for z := 3; z < voxelsZ; z++ { + err := m.WriteInpLayers( + strings.Replace(specs.LayerByLayerPathResult, "#", fmt.Sprintf("%d", z), 1), + 0, z, + float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), + restraintsConvert(restraints), + loadsConvert(loads), + v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + ) + if err != nil { + return err + } + fmt.Printf("Finite elements are generated from layer 0 to layer %v out of %v total.\n", z, voxelsZ-1) + } + + return nil +} + +func restraintsConvert(rs []Restraint) []*mesh.Restraint { + restraints := make([]*mesh.Restraint, len(rs)) + for i, r := range rs { + restraint := mesh.NewRestraint([]v3.Vec{{X: r.LocX, Y: r.LocY, Z: r.LocZ}}, r.IsFixedX, r.IsFixedY, r.IsFixedZ) + restraints[i] = restraint + } + return restraints +} + +func loadsConvert(ls []Load) []*mesh.Load { + loads := make([]*mesh.Load, len(ls)) + for i, l := range ls { + load := mesh.NewLoad([]v3.Vec{{X: l.LocX, Y: l.LocY, Z: l.LocZ}}, v3.Vec{X: l.MagX, Y: l.MagY, Z: l.MagZ}) + loads[i] = load + } + return loads +} + +// TODO: For 3D print analysis, all the voxels at the same Z layer are considered as restraint. +// Since, the 3D print floor is at the same Z level. diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go new file mode 100644 index 000000000..5635867ce --- /dev/null +++ b/examples/finite_elements_print3d/main_test.go @@ -0,0 +1,329 @@ +//----------------------------------------------------------------------------- + +/* + +Finite elements from triangle mesh. +The result `inp` file is consumable by ABAQUS or CalculiX. + +*/ + +//----------------------------------------------------------------------------- + +package main + +import ( + "encoding/json" + "os" + "path/filepath" + "testing" +) + +// Benchmark reference: +// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections +func Test_main(t *testing.T) { + tests := []struct { + skip bool + name string + pathSpecs string // File to be created by test. + specs Specs + loads []Load // If load is zero, gravity would be the dominant force. + restraints []Restraint + }{ + { + skip: false, + name: "benchmarkSquare", + pathSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), + specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: false, + LayerByLayerPathResult: "", + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, + restraints: func() []Restraint { + restraints := make([]Restraint, 0) + + gap := 1.0 + var y float64 + for y <= 17.32 { + restraint := Restraint{ + LocX: 0, + LocY: y, + LocZ: 0, + IsFixedX: true, + IsFixedY: true, + IsFixedZ: true, + } + restraints = append(restraints, restraint) + y += gap + } + + y = 0 + for y <= 17.32 { + restraint := Restraint{ + LocX: 200, + LocY: y, + LocZ: 0, + IsFixedX: false, + IsFixedY: true, + IsFixedZ: true, + } + restraints = append(restraints, restraint) + y += gap + } + return restraints + }(), + }, + { + skip: false, + name: "benchmarkCircle", + pathSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), + specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: false, + LayerByLayerPathResult: "", + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, + restraints: []Restraint{ + {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + }, + }, + { + skip: false, + name: "benchmarkPipe", + pathSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), + specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: false, + LayerByLayerPathResult: "", + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, + restraints: []Restraint{ + {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, + }, + }, + { + skip: false, + name: "benchmarkI", + pathSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), + specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: false, + LayerByLayerPathResult: "", + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 0, + MagX: 0, + MagY: 0, + MagZ: 0, + }, + }, + restraints: func() []Restraint { + restraints := make([]Restraint, 0) + + gap := 1.0 + var y float64 + for y <= 25 { + restraints = append(restraints, Restraint{LocX: 0, LocY: y, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}) + y += gap + } + + y = 0 + for y <= 25 { + restraints = append(restraints, Restraint{LocX: 200, LocY: y, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}) + y += gap + } + + return restraints + }(), + }, + { + skip: false, + name: "teapot", + pathSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), + specs: Specs{ + PathStl: filepath.Join("..", "..", "files", "teapot.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "teapot-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "teapot-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "teapot-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + LayerByLayerfor3dPrintAnalysis: true, + LayerByLayerPathResult: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + loads: []Load{ + { + LocX: 0, + LocY: 0, + LocZ: 8.0, + MagX: 0, + MagY: 0, + MagZ: -10, + }, + }, + restraints: []Restraint{ + {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: 2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: -2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + jsonData, err := json.MarshalIndent(tt.specs, "", " ") + if err != nil { + t.Error(err) + return + } + err = os.WriteFile(tt.pathSpecs, jsonData, 0644) + if err != nil { + t.Error(err) + return + } + + jsonData, err = json.MarshalIndent(tt.loads, "", " ") + if err != nil { + t.Error(err) + return + } + + err = os.WriteFile(tt.specs.PathLoadPoints, jsonData, 0644) + if err != nil { + t.Error(err) + return + } + + jsonData, err = json.MarshalIndent(tt.restraints, "", " ") + if err != nil { + t.Error(err) + return + } + + err = os.WriteFile(tt.specs.PathRestraintPoints, jsonData, 0644) + if err != nil { + t.Error(err) + return + } + + os.Args = []string{ + "executable-name-dummy", + tt.pathSpecs, + } + main() + }) + } +} From 28ac064bbdc95b876a0909acc99014366404104b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 17:06:30 +0330 Subject: [PATCH 738/775] Remove extra code from an example --- examples/finite_elements/main.go | 90 ++++---------- examples/finite_elements/main_test.go | 168 +++++++++----------------- 2 files changed, 84 insertions(+), 174 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 0ac546e7f..b0de5119e 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -11,10 +11,8 @@ package main import ( "encoding/json" - "fmt" "log" "os" - "strings" "github.com/deadsy/sdfx/obj" "github.com/deadsy/sdfx/render" @@ -23,23 +21,21 @@ import ( ) type Specs struct { - PathStl string // Input STL file. - PathLoadPoints string // File containing point loads. - PathRestraintPoints string // File containing point restraints. - PathResult string // Result file, consumable by ABAQUS or CalculiX. - PathResultInfo string // Result details and info. - MassDensity float64 - YoungModulus float64 - PoissonRatio float64 - GravityDirectionX float64 - GravityDirectionY float64 - GravityDirectionZ float64 - GravityMagnitude float64 - Resolution int // Number of voxels on the longest axis of 3D model AABB. - LayerByLayerfor3dPrintAnalysis bool // If true, multiple results will be created layer-by-layer to simulated 3D print process. - LayerByLayerPathResult string // Only relevant if layer-by-layer is true. Must include "#" character as placeholder for layer number. - NonlinearConsidered bool // If true, nonlinear finite elements are generated. - ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. + PathStl string // Input STL file. + PathLoadPoints string // File containing point loads. + PathRestraintPoints string // File containing point restraints. + PathResult string // Result file, consumable by ABAQUS or CalculiX. + PathResultInfo string // Result details and info. + MassDensity float64 + YoungModulus float64 + PoissonRatio float64 + GravityDirectionX float64 + GravityDirectionY float64 + GravityDirectionZ float64 + GravityMagnitude float64 + Resolution int // Number of voxels on the longest axis of 3D model AABB. + NonlinearConsidered bool // If true, nonlinear finite elements are generated. + ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. } type Restraint struct { @@ -159,55 +155,20 @@ func main() { log.Fatalf(err.Error()) } - if !specs.LayerByLayerfor3dPrintAnalysis { - // Generate finite elements for all layers of mesh. - err = m.WriteInp( - specs.PathResult, - float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), - restraintsConvert(restraints), - loadsConvert(loads), - v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, - ) - } else { - err = LayerByLayer(specs, restraints, loads, m, voxelsZ) - } + // Generate finite elements for all layers of mesh. + err = m.WriteInp( + specs.PathResult, + float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), + restraintsConvert(restraints), + loadsConvert(loads), + v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + ) + if err != nil { log.Fatalf(err.Error()) } } -// Generate finite elements layer-by-layer. -// Applicable to 3D print analysis that is done layer-by-layer. -func LayerByLayer( - specs Specs, - restraints []Restraint, - loads []Load, - m *mesh.Fem, - voxelsZ int, -) error { - if voxelsZ < 8 { - return fmt.Errorf("not enough voxel layers along the Z axis %d", voxelsZ) - } - - // The first few layers are ignored. - for z := 3; z < voxelsZ; z++ { - err := m.WriteInpLayers( - strings.Replace(specs.LayerByLayerPathResult, "#", fmt.Sprintf("%d", z), 1), - 0, z, - float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), - restraintsConvert(restraints), - loadsConvert(loads), - v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, - ) - if err != nil { - return err - } - fmt.Printf("Finite elements are generated from layer 0 to layer %v out of %v total.\n", z, voxelsZ-1) - } - - return nil -} - func restraintsConvert(rs []Restraint) []*mesh.Restraint { restraints := make([]*mesh.Restraint, len(rs)) for i, r := range rs { @@ -225,6 +186,3 @@ func loadsConvert(ls []Load) []*mesh.Load { } return loads } - -// TODO: For 3D print analysis, all the voxels at the same Z layer are considered as restraint. -// Since, the 3D print floor is at the same Z level. diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 5635867ce..aba8e763c 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -34,23 +34,21 @@ func Test_main(t *testing.T) { name: "benchmarkSquare", pathSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: false, - LayerByLayerPathResult: "", - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { @@ -101,23 +99,21 @@ func Test_main(t *testing.T) { name: "benchmarkCircle", pathSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: false, - LayerByLayerPathResult: "", - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { @@ -147,23 +143,21 @@ func Test_main(t *testing.T) { name: "benchmarkPipe", pathSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: false, - LayerByLayerPathResult: "", - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { @@ -193,23 +187,21 @@ func Test_main(t *testing.T) { name: "benchmarkI", pathSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: false, - LayerByLayerPathResult: "", - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), + PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), + PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, + Resolution: 50, + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, loads: []Load{ { @@ -240,46 +232,6 @@ func Test_main(t *testing.T) { return restraints }(), }, - { - skip: false, - name: "teapot", - pathSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), - specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "teapot.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "teapot-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "teapot-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "teapot-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: true, - LayerByLayerPathResult: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - }, - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 8.0, - MagX: 0, - MagY: 0, - MagZ: -10, - }, - }, - restraints: []Restraint{ - {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: -2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - }, - }, } for _, tt := range tests { From 0534b3a8d20bf3ea01e5eaab92cbeef9c5c2ddbb Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 3 Sep 2023 18:02:24 +0330 Subject: [PATCH 739/775] Simplify for 3D print applications --- examples/finite_elements_print3d/README.md | 77 +---- examples/finite_elements_print3d/main.go | 118 ++----- examples/finite_elements_print3d/main_test.go | 291 +----------------- sdf/finiteelements/buffer/voxel.go | 17 + sdf/finiteelements/mesh/fem.go | 6 + sdf/finiteelements/mesh/inp.go | 6 +- sdf/finiteelements/mesh/restraint_load.go | 10 + 7 files changed, 88 insertions(+), 437 deletions(-) diff --git a/examples/finite_elements_print3d/README.md b/examples/finite_elements_print3d/README.md index 9bd8e7814..1180e5d23 100644 --- a/examples/finite_elements_print3d/README.md +++ b/examples/finite_elements_print3d/README.md @@ -1,76 +1,5 @@ -# Output +# Finite elements for 3D print analysis -## Nodes and elements +## Layer-by-layer along Z axis -Output is generated as `inp` files for ABAQUS or CalculiX. Nodes and elements are saved in separate files, which are then included inside a single, final `inp` file. This final `inp` file can be opened and viewed using [FreeCAD](https://en.wikipedia.org/wiki/FreeCAD). - -## Loading - -The final `inp` file applies a distributed *gravity* load to all elements. Additional point loads are defined by a JSON file. - -## Boundary - -In the final `inp` file, the boundary is defined by the point restraints inside a JSON file. - -## Modification - -Currently, a convenient way for making adjustments is provided. Simply modify the load, restraint, and specification JSON files. Examining the unit tests is helpful to figure out how. - -# CCX and CGX - -The results can be consumed by ABAQUS or CalculiX. - -CalculiX and CalculiX GraphiX binaries are available for different platforms, like Linux distributions. - -## openSUSE - -openSUSE has [CCX](https://software.opensuse.org/package/ccx) package and also [CGX](https://software.opensuse.org/package/cgx) one. - -To install CCX and CGX on openSUSE Leap 15.5 you can run as root: - -```bash -zypper addrepo https://download.opensuse.org/repositories/science/15.5/science.repo -zypper refresh -zypper install ccx -zypper install cgx -``` - -# Visualize `inp` file - -To visualize the `inp` file by CalculiX GraphiX: - -```bash -cgx -c hex8.inp -``` - -# Analyze `inp` file - -To run the `inp` files by FEA engines like CalculiX: - -```bash -ccx -i hex8 -``` - -The above `-i` flag expects a `hex8.inp` file. - -The above command creates `frd` files containing the results. They can be viewed by CalculiX GraphiX: - -```bash -cgx hex8.frd -``` - -The boundary conditions and loads used in the calculation will be available together with the results if you run: - -```bash -cgx hex8.frd hex8.inp -``` - -## Math solver - -The default CCX math solver is `SPOOLES` which is slow. Apparently `PARDISO` is faster and `PaStiX` is the fastest. But it's needed to build the CCX with `PARDISO` or `PaStiX` math libraries. - -### PARDISO - -#### Linux executable with the Intel Pardiso Solver - -You can download [here](https://www.dropbox.com/s/x8axi53l9dk9w4g/ccx_2.19_MT?dl=1) an executable with the Intel Pardiso solver for x86_64 Linux systems. The executable has all the libraries statically linked into it. So it should run by itself without any dependency. Thanks to [these guys](https://www.feacluster.com/calculix.php). +The result is generated layer-by-layer along the Z axis. Just like the 3D print process itself. The result is in the form of `inp` files for ABAQUS or CalculiX diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 0ac546e7f..49ffb268b 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -23,23 +23,19 @@ import ( ) type Specs struct { - PathStl string // Input STL file. - PathLoadPoints string // File containing point loads. - PathRestraintPoints string // File containing point restraints. - PathResult string // Result file, consumable by ABAQUS or CalculiX. - PathResultInfo string // Result details and info. - MassDensity float64 - YoungModulus float64 - PoissonRatio float64 - GravityDirectionX float64 - GravityDirectionY float64 - GravityDirectionZ float64 - GravityMagnitude float64 - Resolution int // Number of voxels on the longest axis of 3D model AABB. - LayerByLayerfor3dPrintAnalysis bool // If true, multiple results will be created layer-by-layer to simulated 3D print process. - LayerByLayerPathResult string // Only relevant if layer-by-layer is true. Must include "#" character as placeholder for layer number. - NonlinearConsidered bool // If true, nonlinear finite elements are generated. - ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. + PathStl string // Input STL file. + PathResult string // Result file, consumable by ABAQUS or CalculiX. Must include "#" character as placeholder for layer number. + PathResultInfo string // Result details and info. + MassDensity float64 + YoungModulus float64 + PoissonRatio float64 + GravityDirectionX float64 + GravityDirectionY float64 + GravityDirectionZ float64 + GravityMagnitude float64 + Resolution int // Number of voxels on the longest axis of 3D model AABB. + NonlinearConsidered bool // If true, nonlinear finite elements are generated. + ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. } type Restraint struct { @@ -93,28 +89,6 @@ func main() { log.Fatalf(err.Error()) } - jsonData, err = os.ReadFile(specs.PathLoadPoints) - if err != nil { - log.Fatalf(err.Error()) - } - - var loads []Load - err = json.Unmarshal(jsonData, &loads) - if err != nil { - log.Fatalf(err.Error()) - } - - jsonData, err = os.ReadFile(specs.PathRestraintPoints) - if err != nil { - log.Fatalf(err.Error()) - } - - var restraints []Restraint - err = json.Unmarshal(jsonData, &restraints) - if err != nil { - log.Fatalf(err.Error()) - } - // create the SDF from the STL mesh inSdf, err := obj.ImportSTL(specs.PathStl, 20, 3, 5) if err != nil { @@ -159,72 +133,40 @@ func main() { log.Fatalf(err.Error()) } - if !specs.LayerByLayerfor3dPrintAnalysis { - // Generate finite elements for all layers of mesh. - err = m.WriteInp( - specs.PathResult, - float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), - restraintsConvert(restraints), - loadsConvert(loads), - v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, - ) - } else { - err = LayerByLayer(specs, restraints, loads, m, voxelsZ) - } - if err != nil { - log.Fatalf(err.Error()) - } -} + // Generate finite elements layer-by-layer. + // Applicable to 3D print analysis that is done layer-by-layer. -// Generate finite elements layer-by-layer. -// Applicable to 3D print analysis that is done layer-by-layer. -func LayerByLayer( - specs Specs, - restraints []Restraint, - loads []Load, - m *mesh.Fem, - voxelsZ int, -) error { if voxelsZ < 8 { - return fmt.Errorf("not enough voxel layers along the Z axis %d", voxelsZ) + log.Fatalf("not enough voxel layers along the Z axis %d", voxelsZ) } // The first few layers are ignored. for z := 3; z < voxelsZ; z++ { err := m.WriteInpLayers( - strings.Replace(specs.LayerByLayerPathResult, "#", fmt.Sprintf("%d", z), 1), + strings.Replace(specs.PathResult, "#", fmt.Sprintf("%d", z), 1), 0, z, float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), - restraintsConvert(restraints), - loadsConvert(loads), + restraintsPrintFloor(m), + []*mesh.Load{}, // Load is empty since only gravity is assumed responsible for 3D print collapse. v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, ) if err != nil { - return err + log.Fatalf(err.Error()) } fmt.Printf("Finite elements are generated from layer 0 to layer %v out of %v total.\n", z, voxelsZ-1) } - return nil -} - -func restraintsConvert(rs []Restraint) []*mesh.Restraint { - restraints := make([]*mesh.Restraint, len(rs)) - for i, r := range rs { - restraint := mesh.NewRestraint([]v3.Vec{{X: r.LocX, Y: r.LocY, Z: r.LocZ}}, r.IsFixedX, r.IsFixedY, r.IsFixedZ) - restraints[i] = restraint + if err != nil { + log.Fatalf(err.Error()) } - return restraints } -func loadsConvert(ls []Load) []*mesh.Load { - loads := make([]*mesh.Load, len(ls)) - for i, l := range ls { - load := mesh.NewLoad([]v3.Vec{{X: l.LocX, Y: l.LocY, Z: l.LocZ}}, v3.Vec{X: l.MagX, Y: l.MagY, Z: l.MagZ}) - loads[i] = load - } - return loads +// For 3D print analysis, all the voxels at the first layer along Z axis are considered as restraint. +// Since, the 3D print floor is at the first Z level. +func restraintsPrintFloor(m *mesh.Fem) []*mesh.Restraint { + restraints := make([]*mesh.Restraint, 1) + voxels := m.VoxelsOn1stLayerZ() + restraint := mesh.NewRestraintByVoxel(voxels, true, true, true) + restraints[0] = restraint + return restraints } - -// TODO: For 3D print analysis, all the voxels at the same Z layer are considered as restraint. -// Since, the 3D print floor is at the same Z level. diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go index 5635867ce..f095ae3b8 100644 --- a/examples/finite_elements_print3d/main_test.go +++ b/examples/finite_elements_print3d/main_test.go @@ -22,262 +22,29 @@ import ( // https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections func Test_main(t *testing.T) { tests := []struct { - skip bool - name string - pathSpecs string // File to be created by test. - specs Specs - loads []Load // If load is zero, gravity would be the dominant force. - restraints []Restraint + skip bool + name string + pathSpecs string // File to be created by test. + specs Specs }{ - { - skip: false, - name: "benchmarkSquare", - pathSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), - specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: false, - LayerByLayerPathResult: "", - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - }, - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - }, - restraints: func() []Restraint { - restraints := make([]Restraint, 0) - - gap := 1.0 - var y float64 - for y <= 17.32 { - restraint := Restraint{ - LocX: 0, - LocY: y, - LocZ: 0, - IsFixedX: true, - IsFixedY: true, - IsFixedZ: true, - } - restraints = append(restraints, restraint) - y += gap - } - - y = 0 - for y <= 17.32 { - restraint := Restraint{ - LocX: 200, - LocY: y, - LocZ: 0, - IsFixedX: false, - IsFixedY: true, - IsFixedZ: true, - } - restraints = append(restraints, restraint) - y += gap - } - return restraints - }(), - }, - { - skip: false, - name: "benchmarkCircle", - pathSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), - specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: false, - LayerByLayerPathResult: "", - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - }, - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - }, - restraints: []Restraint{ - {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - }, - }, - { - skip: false, - name: "benchmarkPipe", - pathSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), - specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: false, - LayerByLayerPathResult: "", - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - }, - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - }, - restraints: []Restraint{ - {LocX: 0, LocY: 0, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: -2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: -3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: 2.0313, LocZ: 0.213498, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 0, LocY: 3.97382, LocZ: 0.844661, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 0, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: -2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: -3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 2.0313, LocZ: 0.213498, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - {LocX: 200, LocY: 3.97382, LocZ: 0.844661, IsFixedX: false, IsFixedY: true, IsFixedZ: true}, - }, - }, - { - skip: false, - name: "benchmarkI", - pathSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), - specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: false, - LayerByLayerPathResult: "", - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - }, - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 0, - MagX: 0, - MagY: 0, - MagZ: 0, - }, - }, - restraints: func() []Restraint { - restraints := make([]Restraint, 0) - - gap := 1.0 - var y float64 - for y <= 25 { - restraints = append(restraints, Restraint{LocX: 0, LocY: y, LocZ: 0, IsFixedX: true, IsFixedY: true, IsFixedZ: true}) - y += gap - } - - y = 0 - for y <= 25 { - restraints = append(restraints, Restraint{LocX: 200, LocY: y, LocZ: 0, IsFixedX: false, IsFixedY: true, IsFixedZ: true}) - y += gap - } - - return restraints - }(), - }, { skip: false, name: "teapot", pathSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "teapot.stl"), - PathLoadPoints: filepath.Join(os.TempDir(), "teapot-load-points.json"), - PathRestraintPoints: filepath.Join(os.TempDir(), "teapot-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "teapot-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: -1, - GravityMagnitude: 9810, - Resolution: 50, - LayerByLayerfor3dPrintAnalysis: true, - LayerByLayerPathResult: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), - NonlinearConsidered: false, - ExactSurfaceConsidered: true, - }, - loads: []Load{ - { - LocX: 0, - LocY: 0, - LocZ: 8.0, - MagX: 0, - MagY: 0, - MagZ: -10, - }, - }, - restraints: []Restraint{ - {LocX: -2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 2.5, LocY: 2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: 2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, - {LocX: -2.5, LocY: -2.5, LocZ: 0.3, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + PathStl: filepath.Join("..", "..", "files", "teapot.stl"), + PathResult: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: +1, // SLA 3D print is usually done upside down. + GravityMagnitude: 9810, + Resolution: 50, + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, }, } @@ -295,30 +62,6 @@ func Test_main(t *testing.T) { return } - jsonData, err = json.MarshalIndent(tt.loads, "", " ") - if err != nil { - t.Error(err) - return - } - - err = os.WriteFile(tt.specs.PathLoadPoints, jsonData, 0644) - if err != nil { - t.Error(err) - return - } - - jsonData, err = json.MarshalIndent(tt.restraints, "", " ") - if err != nil { - t.Error(err) - return - } - - err = os.WriteFile(tt.specs.PathRestraintPoints, jsonData, 0644) - if err != nil { - t.Error(err) - return - } - os.Args = []string{ "executable-name-dummy", tt.pathSpecs, diff --git a/sdf/finiteelements/buffer/voxel.go b/sdf/finiteelements/buffer/voxel.go index 3fe9d5094..8b37b5e9e 100644 --- a/sdf/finiteelements/buffer/voxel.go +++ b/sdf/finiteelements/buffer/voxel.go @@ -172,3 +172,20 @@ func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { } } } + +//----------------------------------------------------------------------------- + +func (vg *VoxelGrid) VoxelsOn1stLayerZ() []v3i.Vec { + voxels := make([]v3i.Vec, 0) + z := 0 // 1st layer along Z axis. + for y := 0; y < vg.Len.Y; y++ { + for x := 0; x < vg.Len.X; x++ { + elements := vg.Get(x, y, z) + if len(elements) < 1 { + continue + } + voxels = append(voxels, v3i.Vec{X: x, Y: y, Z: z}) + } + } + return voxels +} diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 5966ef612..6ca5a834d 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -131,6 +131,12 @@ func (m *Fem) VoxelsIntersecting(points []v3.Vec) ([]v3i.Vec, v3.Vec, v3.Vec) { //----------------------------------------------------------------------------- +func (m *Fem) VoxelsOn1stLayerZ() []v3i.Vec { + return m.IBuff.Grid.VoxelsOn1stLayerZ() +} + +//----------------------------------------------------------------------------- + // Count separate components consisting of disconnected finite elements. // They cause FEA solver to throw error. func (m *Fem) Components() []*buffer.Component { diff --git a/sdf/finiteelements/mesh/inp.go b/sdf/finiteelements/mesh/inp.go index 93b60eab6..6dd7fb0ee 100644 --- a/sdf/finiteelements/mesh/inp.go +++ b/sdf/finiteelements/mesh/inp.go @@ -361,7 +361,11 @@ func (inp *Inp) writeBoundary() error { // Figure out reference node and voxels for each restraint. for _, r := range inp.Restraints { - r.voxels, _, _ = inp.Mesh.VoxelsIntersecting(r.Location) + // Only set voxels only if they are not already set. + // If voxels are already set, it means the caller has decided about voxels. + if len(r.voxels) < 1 { + r.voxels, _, _ = inp.Mesh.VoxelsIntersecting(r.Location) + } } for i, r := range inp.Restraints { diff --git a/sdf/finiteelements/mesh/restraint_load.go b/sdf/finiteelements/mesh/restraint_load.go index a96c0fd60..95703bc23 100644 --- a/sdf/finiteelements/mesh/restraint_load.go +++ b/sdf/finiteelements/mesh/restraint_load.go @@ -40,6 +40,16 @@ func NewRestraint(location []v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restrai } } +func NewRestraintByVoxel(voxels []v3i.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { + return &Restraint{ + Location: []v3.Vec{}, + IsFixedX: isFixedX, + IsFixedY: isFixedY, + IsFixedZ: isFixedZ, + voxels: voxels, + } +} + func NewLoad(location []v3.Vec, magnitude v3.Vec) *Load { return &Load{ Location: location, From 9f9d5df083a9ccdb8234d13d3cb1c4ec6fac865e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 11:23:00 +0330 Subject: [PATCH 740/775] Fix: end layer is excluded --- examples/finite_elements_print3d/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 49ffb268b..5b349dc1f 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -141,10 +141,10 @@ func main() { } // The first few layers are ignored. - for z := 3; z < voxelsZ; z++ { + for z := 3; z <= voxelsZ; z++ { err := m.WriteInpLayers( strings.Replace(specs.PathResult, "#", fmt.Sprintf("%d", z), 1), - 0, z, + 0, z, // Note that the start layer is included, the end layer is excluded. float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), restraintsPrintFloor(m), []*mesh.Load{}, // Load is empty since only gravity is assumed responsible for 3D print collapse. From 64a9ceb0f226ac379af191c85047e89a1916ff6b Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 11:46:07 +0330 Subject: [PATCH 741/775] See if gravity is needed --- sdf/finiteelements/mesh/fem.go | 6 +- sdf/finiteelements/mesh/inp.go | 137 ++++++++++++++++++++------------- 2 files changed, 86 insertions(+), 57 deletions(-) diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 6ca5a834d..91db644c6 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -159,9 +159,10 @@ func (m *Fem) WriteInp( loads []*Load, gravityDirection v3.Vec, gravityMagnitude float64, + gravityIsNeeded bool, ) error { _, _, layersZ := m.IBuff.Size() - return m.WriteInpLayers(path, 0, layersZ, massDensity, youngModulus, poissonRatio, restraints, loads, gravityDirection, gravityMagnitude) + return m.WriteInpLayers(path, 0, layersZ, massDensity, youngModulus, poissonRatio, restraints, loads, gravityDirection, gravityMagnitude, gravityIsNeeded) } // WriteInpLayers writes specific layers of mesh to ABAQUS or CalculiX `inp` file. @@ -177,8 +178,9 @@ func (m *Fem) WriteInpLayers( loads []*Load, gravityDirection v3.Vec, gravityMagnitude float64, + gravityIsNeeded bool, ) error { - inp := NewInp(m, path, layerStart, layerEnd, massDensity, youngModulus, poissonRatio, restraints, loads, gravityDirection, gravityMagnitude) + inp := NewInp(m, path, layerStart, layerEnd, massDensity, youngModulus, poissonRatio, restraints, loads, gravityDirection, gravityMagnitude, gravityIsNeeded) return inp.Write() } diff --git a/sdf/finiteelements/mesh/inp.go b/sdf/finiteelements/mesh/inp.go index 6dd7fb0ee..c14903433 100644 --- a/sdf/finiteelements/mesh/inp.go +++ b/sdf/finiteelements/mesh/inp.go @@ -29,6 +29,9 @@ type Inp struct { PathBou string // For writing loads to a separate file. PathLoad string + // For writing gravity to a separate file. + PathGravity string + GravityIsNeeded bool // Output `inp` file would include start layer. LayerStart int // Output `inp` file would exclude end layer. @@ -63,6 +66,7 @@ func NewInp( loads []*Load, gravityDirection v3.Vec, gravityMagnitude float64, + gravityIsNeeded bool, ) *Inp { inp := &Inp{ Mesh: m, @@ -74,6 +78,8 @@ func NewInp( PathElsC3D20R: path + ".elements_C3D20R", PathBou: path + ".boundary", PathLoad: path + ".load", + PathGravity: path + ".gravity", + GravityIsNeeded: gravityIsNeeded, LayerStart: layerStart, LayerEnd: layerEnd, TempVBuff: buffer.NewVB(), @@ -547,6 +553,72 @@ func (inp *Inp) writeLoad() error { return nil } +func (inp *Inp) writeGravity() error { + // Write to a separate file to avoid cluttering the `inp` file. + f, err := os.Create(inp.PathGravity) + if err != nil { + return err + } + defer f.Close() + + // Write distributed loads. + + _, err = f.WriteString("*DLOAD\n") + if err != nil { + return err + } + + // Assign gravity loading in any direction with any magnitude to all elements. + // + // 9810 could be gravity magnitude in mm/sec^2 units. + // + // SLA 3D printing is done upside-down. 3D model is hanging from the print floor. + // That's why gravity could be in "positive" z-direction. + // Here ”gravity” really stands for any acceleration vector. + // + // Refer to CalculiX solver documentation: + // http://www.dhondt.de/ccx_2.20.pdf + _, err = f.WriteString( + fmt.Sprintf( + "eC3D4,GRAV,%v,%v,%v,%v\n", + inp.GravityMagnitude, + inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, + ), + ) + if err != nil { + return err + } + _, err = f.WriteString( + fmt.Sprintf( + "eC3D10,GRAV,%v,%v,%v,%v\n", + inp.GravityMagnitude, + inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, + ), + ) + if err != nil { + return err + } + _, err = f.WriteString( + fmt.Sprintf( + "eC3D8,GRAV,%v,%v,%v,%v\n", + inp.GravityMagnitude, + inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, + ), + ) + if err != nil { + return err + } + _, err = f.WriteString( + fmt.Sprintf( + "eC3D20R,GRAV,%v,%v,%v,%v\n", + inp.GravityMagnitude, + inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, + ), + ) + + return err +} + func (inp *Inp) writeFooter(f *os.File) error { // Define material. @@ -616,62 +688,17 @@ func (inp *Inp) writeFooter(f *os.File) error { return err } - // Write distributed loads. - - _, err = f.WriteString("*DLOAD\n") - if err != nil { - return err - } + if inp.GravityIsNeeded { + // Include a separate file to avoid cluttering the `inp` file. + _, err = f.WriteString(fmt.Sprintf("*INCLUDE,INPUT=%s\n", inp.PathGravity)) + if err != nil { + return err + } - // Assign gravity loading in any direction with any magnitude to all elements. - // - // 9810 could be gravity magnitude in mm/sec^2 units. - // - // SLA 3D printing is done upside-down. 3D model is hanging from the print floor. - // That's why gravity could be in "positive" z-direction. - // Here ”gravity” really stands for any acceleration vector. - // - // Refer to CalculiX solver documentation: - // http://www.dhondt.de/ccx_2.20.pdf - _, err = f.WriteString( - fmt.Sprintf( - "eC3D4,GRAV,%v,%v,%v,%v\n", - inp.GravityMagnitude, - inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, - ), - ) - if err != nil { - return err - } - _, err = f.WriteString( - fmt.Sprintf( - "eC3D10,GRAV,%v,%v,%v,%v\n", - inp.GravityMagnitude, - inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, - ), - ) - if err != nil { - return err - } - _, err = f.WriteString( - fmt.Sprintf( - "eC3D8,GRAV,%v,%v,%v,%v\n", - inp.GravityMagnitude, - inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, - ), - ) - if err != nil { - return err - } - _, err = f.WriteString( - fmt.Sprintf( - "eC3D20R,GRAV,%v,%v,%v,%v\n", - inp.GravityMagnitude, - inp.GravityDirection.X, inp.GravityDirection.Y, inp.GravityDirection.Z, - ), - ) - if err != nil { - return err + err = inp.writeGravity() + if err != nil { + return err + } } // Pick element results. From 6f13da7afbee317ef854083b9a7f115fbc53cad0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 11:47:14 +0330 Subject: [PATCH 742/775] Gravity is always needed for 3D print analysis --- examples/finite_elements_print3d/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 5b349dc1f..ede99cae5 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -149,6 +149,7 @@ func main() { restraintsPrintFloor(m), []*mesh.Load{}, // Load is empty since only gravity is assumed responsible for 3D print collapse. v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + true, ) if err != nil { log.Fatalf(err.Error()) From 9a7f3c75ff95506d3ba56469d9c1e9615719e117 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 11:50:02 +0330 Subject: [PATCH 743/775] Pass arg: gravity is needed? --- examples/finite_elements/main.go | 2 ++ examples/finite_elements/main_test.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index b0de5119e..563849973 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -33,6 +33,7 @@ type Specs struct { GravityDirectionY float64 GravityDirectionZ float64 GravityMagnitude float64 + GravityIsNeeded bool Resolution int // Number of voxels on the longest axis of 3D model AABB. NonlinearConsidered bool // If true, nonlinear finite elements are generated. ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. @@ -162,6 +163,7 @@ func main() { restraintsConvert(restraints), loadsConvert(loads), v3.Vec{X: specs.GravityDirectionX, Y: specs.GravityDirectionY, Z: specs.GravityDirectionZ}, specs.GravityMagnitude, + specs.GravityIsNeeded, ) if err != nil { diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index aba8e763c..aa9a15659 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -46,6 +46,7 @@ func Test_main(t *testing.T) { GravityDirectionY: 0, GravityDirectionZ: -1, GravityMagnitude: 9810, + GravityIsNeeded: true, Resolution: 50, NonlinearConsidered: false, ExactSurfaceConsidered: true, @@ -111,6 +112,7 @@ func Test_main(t *testing.T) { GravityDirectionY: 0, GravityDirectionZ: -1, GravityMagnitude: 9810, + GravityIsNeeded: true, Resolution: 50, NonlinearConsidered: false, ExactSurfaceConsidered: true, @@ -155,6 +157,7 @@ func Test_main(t *testing.T) { GravityDirectionY: 0, GravityDirectionZ: -1, GravityMagnitude: 9810, + GravityIsNeeded: true, Resolution: 50, NonlinearConsidered: false, ExactSurfaceConsidered: true, @@ -199,6 +202,7 @@ func Test_main(t *testing.T) { GravityDirectionY: 0, GravityDirectionZ: -1, GravityMagnitude: 9810, + GravityIsNeeded: true, Resolution: 50, NonlinearConsidered: false, ExactSurfaceConsidered: true, From 5592f96728095bd4c9319ad0aa4fa5b6bb413420 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 11:53:28 +0330 Subject: [PATCH 744/775] Comment --- sdf/finiteelements/mesh/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdf/finiteelements/mesh/inp.go b/sdf/finiteelements/mesh/inp.go index c14903433..7331bd9ec 100644 --- a/sdf/finiteelements/mesh/inp.go +++ b/sdf/finiteelements/mesh/inp.go @@ -367,7 +367,7 @@ func (inp *Inp) writeBoundary() error { // Figure out reference node and voxels for each restraint. for _, r := range inp.Restraints { - // Only set voxels only if they are not already set. + // Set voxels, if they are not already set. // If voxels are already set, it means the caller has decided about voxels. if len(r.voxels) < 1 { r.voxels, _, _ = inp.Mesh.VoxelsIntersecting(r.Location) From 573775ec89a40d109e63b9ae61e2d834b0da5bd5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 12:26:21 +0330 Subject: [PATCH 745/775] Setup load & restraint --- sdf/finiteelements/mesh/fem.go | 28 +++++++++++++++++++++++ sdf/finiteelements/mesh/restraint_load.go | 9 ++++++++ 2 files changed, 37 insertions(+) diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 91db644c6..f2354244e 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -180,8 +180,36 @@ func (m *Fem) WriteInpLayers( gravityMagnitude float64, gravityIsNeeded bool, ) error { + restraints = restraintSetup(m, restraints) + loads = loadSetup(m, loads) inp := NewInp(m, path, layerStart, layerEnd, massDensity, youngModulus, poissonRatio, restraints, loads, gravityDirection, gravityMagnitude, gravityIsNeeded) return inp.Write() } //----------------------------------------------------------------------------- + +func restraintSetup(m *Fem, restraints []*Restraint) []*Restraint { + // Figure out voxels for each. + for _, r := range restraints { + // Set voxels, if they are not already set. + // If voxels are already set, it means the caller has decided about voxels. + if len(r.voxels) < 1 { + r.voxels, _, _ = m.VoxelsIntersecting(r.Location) + } + } + return restraints +} + +func loadSetup(m *Fem, loads []*Load) []*Load { + // Figure out voxels for each. + for _, l := range loads { + // Set voxels, if they are not already set. + // If voxels are already set, it means the caller has decided about voxels. + if len(l.voxels) < 1 { + l.voxels, _, _ = m.VoxelsIntersecting(l.Location) + } + } + return loads +} + +//----------------------------------------------------------------------------- diff --git a/sdf/finiteelements/mesh/restraint_load.go b/sdf/finiteelements/mesh/restraint_load.go index 95703bc23..aa04c9bd5 100644 --- a/sdf/finiteelements/mesh/restraint_load.go +++ b/sdf/finiteelements/mesh/restraint_load.go @@ -58,3 +58,12 @@ func NewLoad(location []v3.Vec, magnitude v3.Vec) *Load { nodeREF: 0, } } + +func NewLoadByVoxel(voxels []v3i.Vec, magnitude v3.Vec) *Load { + return &Load{ + Location: []v3.Vec{}, + Magnitude: magnitude, + voxels: voxels, + nodeREF: 0, + } +} From 8bec49f69246ceff09c588e12ce38fbcf313fda9 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 12:29:31 +0330 Subject: [PATCH 746/775] Remove outdated statements --- sdf/finiteelements/mesh/inp.go | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/sdf/finiteelements/mesh/inp.go b/sdf/finiteelements/mesh/inp.go index 7331bd9ec..29e844fb9 100644 --- a/sdf/finiteelements/mesh/inp.go +++ b/sdf/finiteelements/mesh/inp.go @@ -92,14 +92,6 @@ func NewInp( GravityMagnitude: gravityMagnitude, } - // TODO: complete loading. - // - // Figure out node and voxel for each load. - // TODO: move this statement to the logic that writes loads to file. - for _, l := range inp.Loads { - l.voxels, _, _ = inp.Mesh.VoxelsIntersecting(l.Location) - } - return inp } @@ -365,15 +357,6 @@ func (inp *Inp) writeBoundary() error { } defer f.Close() - // Figure out reference node and voxels for each restraint. - for _, r := range inp.Restraints { - // Set voxels, if they are not already set. - // If voxels are already set, it means the caller has decided about voxels. - if len(r.voxels) < 1 { - r.voxels, _, _ = inp.Mesh.VoxelsIntersecting(r.Location) - } - } - for i, r := range inp.Restraints { isFixedX, isFixedY, isFixedZ := r.IsFixedX, r.IsFixedY, r.IsFixedZ if !isFixedX && !isFixedY && !isFixedZ { @@ -514,13 +497,6 @@ func (inp *Inp) writeLoad() error { return err } - // TODO: complete loading. - - // Figure out node and voxel for each. - for _, l := range inp.Loads { - l.voxels, _, _ = inp.Mesh.VoxelsIntersecting(l.Location) - } - // The closest node to any restraint is already computed. for _, l := range inp.Loads { // Node ID should be consistant with the temp vertex buffer. From e01674454501e9d5ecb3ebb931293901b5e64cd8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 13:56:27 +0330 Subject: [PATCH 747/775] Load & restraint overhaul: a single point & voxel --- examples/finite_elements/main.go | 4 +- examples/finite_elements_print3d/main.go | 7 +-- sdf/finiteelements/mesh/fem.go | 44 ++++++++++++------ sdf/finiteelements/mesh/inp.go | 24 ++++------ sdf/finiteelements/mesh/restraint_load.go | 55 ++++++++++------------- 5 files changed, 69 insertions(+), 65 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 563849973..257051e88 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -174,7 +174,7 @@ func main() { func restraintsConvert(rs []Restraint) []*mesh.Restraint { restraints := make([]*mesh.Restraint, len(rs)) for i, r := range rs { - restraint := mesh.NewRestraint([]v3.Vec{{X: r.LocX, Y: r.LocY, Z: r.LocZ}}, r.IsFixedX, r.IsFixedY, r.IsFixedZ) + restraint := mesh.NewRestraint(v3.Vec{X: r.LocX, Y: r.LocY, Z: r.LocZ}, r.IsFixedX, r.IsFixedY, r.IsFixedZ) restraints[i] = restraint } return restraints @@ -183,7 +183,7 @@ func restraintsConvert(rs []Restraint) []*mesh.Restraint { func loadsConvert(ls []Load) []*mesh.Load { loads := make([]*mesh.Load, len(ls)) for i, l := range ls { - load := mesh.NewLoad([]v3.Vec{{X: l.LocX, Y: l.LocY, Z: l.LocZ}}, v3.Vec{X: l.MagX, Y: l.MagY, Z: l.MagZ}) + load := mesh.NewLoad(v3.Vec{X: l.LocX, Y: l.LocY, Z: l.LocZ}, v3.Vec{X: l.MagX, Y: l.MagY, Z: l.MagZ}) loads[i] = load } return loads diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index ede99cae5..22e36fdfb 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -165,9 +165,10 @@ func main() { // For 3D print analysis, all the voxels at the first layer along Z axis are considered as restraint. // Since, the 3D print floor is at the first Z level. func restraintsPrintFloor(m *mesh.Fem) []*mesh.Restraint { - restraints := make([]*mesh.Restraint, 1) voxels := m.VoxelsOn1stLayerZ() - restraint := mesh.NewRestraintByVoxel(voxels, true, true, true) - restraints[0] = restraint + restraints := make([]*mesh.Restraint, len(voxels)) + for i, voxel := range voxels { + restraints[i] = mesh.NewRestraintByVoxel(voxel, true, true, true) + } return restraints } diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index f2354244e..4d7732a2e 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -1,6 +1,8 @@ package mesh import ( + "fmt" + "log" "math" "github.com/deadsy/sdfx/render" @@ -79,11 +81,11 @@ func (m *Fem) iterate(f func(int, int, int, []*buffer.Element)) { m.IBuff.Iterate(f) } -// The closest node is identified. +// The closest vertex/node is identified. // Also, the containing voxel is figured out. // // This logic has to be here, since we need access to any node vertex. -func (m *Fem) Locate(location v3.Vec) (uint32, v3i.Vec) { +func (m *Fem) Locate(location v3.Vec) (v3.Vec, v3i.Vec) { // Calculating voxel indices. idxX := int(math.Floor((location.X - m.IBuff.Grid.Voxels[0].Min.X) / (m.IBuff.Grid.Dim.X))) idxY := int(math.Floor((location.Y - m.IBuff.Grid.Voxels[0].Min.Y) / (m.IBuff.Grid.Dim.Y))) @@ -104,7 +106,7 @@ func (m *Fem) Locate(location v3.Vec) (uint32, v3i.Vec) { elements := m.IBuff.Grid.Get(idxX, idxY, idxZ) // Find the closest node - var closestNode uint32 + var closestNode v3.Vec minDistance := math.Inf(1) for _, element := range elements { @@ -115,7 +117,7 @@ func (m *Fem) Locate(location v3.Vec) (uint32, v3i.Vec) { distance := location.Sub(nodePos).Length() if distance < minDistance { minDistance = distance - closestNode = node + closestNode = nodePos } } } @@ -189,24 +191,38 @@ func (m *Fem) WriteInpLayers( //----------------------------------------------------------------------------- func restraintSetup(m *Fem, restraints []*Restraint) []*Restraint { - // Figure out voxels for each. + // Figure out voxel for each. for _, r := range restraints { - // Set voxels, if they are not already set. - // If voxels are already set, it means the caller has decided about voxels. - if len(r.voxels) < 1 { - r.voxels, _, _ = m.VoxelsIntersecting(r.Location) + // Set voxel, if not already set. + // If voxel is already set, it means the caller has decided about voxel. + if r.voxel.X == -1 && r.voxel.Y == -1 && r.voxel.Z == -1 { + voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{r.Location}) + if len(voxels) < 1 { + log.Fatalln("no voxel is intersecting with the point restraint") + } + r.voxel = voxels[0] } } return restraints } func loadSetup(m *Fem, loads []*Load) []*Load { - // Figure out voxels for each. + // Figure out voxel for each. for _, l := range loads { - // Set voxels, if they are not already set. - // If voxels are already set, it means the caller has decided about voxels. - if len(l.voxels) < 1 { - l.voxels, _, _ = m.VoxelsIntersecting(l.Location) + // Set voxel, if not already set. + // If voxel is already set, it means the caller has decided about voxel. + if l.voxel.X == -1 && l.voxel.Y == -1 && l.voxel.Z == -1 { + voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{l.Location}) + if len(voxels) < 1 { + log.Fatalln("no voxel is intersecting with the point load") + } + l.voxel = voxels[0] + closestVertex, closestVoxel := m.Locate(l.Location) + l.voxel = closestVoxel + l.nodeREF = closestVertex + if voxels[0].X != closestVoxel.X && voxels[0].Y != closestVoxel.Y && voxels[0].Z != closestVoxel.Z { + fmt.Println("m.VoxelsIntersecting() != m.Locate()") + } } } return loads diff --git a/sdf/finiteelements/mesh/inp.go b/sdf/finiteelements/mesh/inp.go index 29e844fb9..b5829157a 100644 --- a/sdf/finiteelements/mesh/inp.go +++ b/sdf/finiteelements/mesh/inp.go @@ -365,19 +365,14 @@ func (inp *Inp) writeBoundary() error { nodeSet := make([]uint32, 0) - for _, vox := range r.voxels { - - // Get elements in the voxel - elements := inp.Mesh.IBuff.Grid.Get(vox.X, vox.Y, vox.Z) - - for _, element := range elements { - for _, node := range element.Nodes { - // Node ID should be consistant with the temp vertex buffer. - // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. - vertex := inp.Mesh.vertex(node) - id := inp.TempVBuff.Id(vertex) - nodeSet = append(nodeSet, id) - } + elements := inp.Mesh.IBuff.Grid.Get(r.voxel.X, r.voxel.Y, r.voxel.Z) + for _, element := range elements { + for _, node := range element.Nodes { + // Node ID should be consistant with the temp vertex buffer. + // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. + vertex := inp.Mesh.vertex(node) + id := inp.TempVBuff.Id(vertex) + nodeSet = append(nodeSet, id) } } @@ -501,8 +496,7 @@ func (inp *Inp) writeLoad() error { for _, l := range inp.Loads { // Node ID should be consistant with the temp vertex buffer. // Node ID is different on these two: (1) original vertex buffer, (2) temp vertex buffer. - vertex := inp.Mesh.vertex(l.nodeREF) - id := inp.TempVBuff.Id(vertex) + id := inp.TempVBuff.Id(l.nodeREF) // To be written: // diff --git a/sdf/finiteelements/mesh/restraint_load.go b/sdf/finiteelements/mesh/restraint_load.go index aa04c9bd5..97385ddfa 100644 --- a/sdf/finiteelements/mesh/restraint_load.go +++ b/sdf/finiteelements/mesh/restraint_load.go @@ -5,65 +5,58 @@ import ( "github.com/deadsy/sdfx/vec/v3i" ) -// 1. Define each restraint by two things: -// 1.1. A collection of points, *not* by a single point. -// 1.2. Degrees of freedom that are fixed/free for all the points of the collection. -// 2. Assume a bounding box around all those points. -// 3. Any voxel that intersects with the bounding box is considered inside restraint. -// 4. Create `*BOUNDARY` for all the nodes inside those voxels. -// 5. Degree of freedom would be fixed/free for all those nodes. -// -// The objective: the stress concentration at the restraint may be alleviated by distributing it. +// A voxel is detected that intersects with the restraint location. +// Boundary is created for all the nodes inside that voxel. +// This way, the stress concentration at the restraint may be alleviated by distributing it. type Restraint struct { - Location []v3.Vec // Exact coordinates inside restraint. - IsFixedX bool // Is X degree of freedom fixed? - IsFixedY bool // Is Y degree of freedom fixed? - IsFixedZ bool // Is Z degree of freedom fixed? - voxels []v3i.Vec // Intersecting voxels: to be computed by logic. + Location v3.Vec // Exact coordinates inside restraint. + IsFixedX bool // Is X degree of freedom fixed? + IsFixedY bool // Is Y degree of freedom fixed? + IsFixedZ bool // Is Z degree of freedom fixed? + voxel v3i.Vec // Intersecting voxel: to be computed by logic. } -// Point loads are applied to the nodes of the mesh. +// A voxel is detected that intersects with the point load location. +// A vertex inside that voxel is selected, i.e. the vertex closest to load location. +// The vertex is assigned the load. +// This way, point load is applied to a single node/vertex of the mesh. type Load struct { - Location []v3.Vec // Exact coordinates inside restraint. - Magnitude v3.Vec // X, Y, Z magnitude. - voxels []v3i.Vec // Intersecting voxels: to be computed by logic. - nodeREF uint32 // Eventual node to which the load is applied. To be computed. + Location v3.Vec // Exact coordinates inside restraint. + Magnitude v3.Vec // X, Y, Z magnitude. + voxel v3i.Vec // Intersecting voxel: to be computed by logic. + nodeREF v3.Vec // Eventual vertex/node to which the load is applied. To be computed. } -func NewRestraint(location []v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { +func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { return &Restraint{ Location: location, IsFixedX: isFixedX, IsFixedY: isFixedY, IsFixedZ: isFixedZ, - voxels: make([]v3i.Vec, 0), + voxel: v3i.Vec{X: -1, Y: -1, Z: -1}, // We depend on -1 value to see if voxel is valid. } } -func NewRestraintByVoxel(voxels []v3i.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { +func NewRestraintByVoxel(voxel v3i.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { return &Restraint{ - Location: []v3.Vec{}, IsFixedX: isFixedX, IsFixedY: isFixedY, IsFixedZ: isFixedZ, - voxels: voxels, + voxel: voxel, } } -func NewLoad(location []v3.Vec, magnitude v3.Vec) *Load { +func NewLoad(location v3.Vec, magnitude v3.Vec) *Load { return &Load{ Location: location, Magnitude: magnitude, - voxels: make([]v3i.Vec, 0), - nodeREF: 0, + voxel: v3i.Vec{X: -1, Y: -1, Z: -1}, // We depend on -1 value to see if voxel is valid. } } -func NewLoadByVoxel(voxels []v3i.Vec, magnitude v3.Vec) *Load { +func NewLoadByVoxel(voxel v3i.Vec, magnitude v3.Vec) *Load { return &Load{ - Location: []v3.Vec{}, Magnitude: magnitude, - voxels: voxels, - nodeREF: 0, + voxel: voxel, } } From 05b1e8fae207432469df151cb78588305a8029ae Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 4 Sep 2023 15:00:51 +0330 Subject: [PATCH 748/775] Update read-me --- examples/finite_elements/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/README.md b/examples/finite_elements/README.md index 9bd8e7814..80d682a0f 100644 --- a/examples/finite_elements/README.md +++ b/examples/finite_elements/README.md @@ -6,7 +6,7 @@ Output is generated as `inp` files for ABAQUS or CalculiX. Nodes and elements ar ## Loading -The final `inp` file applies a distributed *gravity* load to all elements. Additional point loads are defined by a JSON file. +The final `inp` file can apply a distributed *gravity* load to all elements. Additional point loads can be defined by a JSON file. ## Boundary From 824427d5407b4b717b4baaf760558b0ca38e62f0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 09:10:39 +0330 Subject: [PATCH 749/775] Rename --- examples/finite_elements_print3d/main.go | 28 +++++++++---------- examples/finite_elements_print3d/main_test.go | 26 ++++++++--------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 22e36fdfb..1b7fb61ca 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -23,19 +23,19 @@ import ( ) type Specs struct { - PathStl string // Input STL file. - PathResult string // Result file, consumable by ABAQUS or CalculiX. Must include "#" character as placeholder for layer number. - PathResultInfo string // Result details and info. - MassDensity float64 - YoungModulus float64 - PoissonRatio float64 - GravityDirectionX float64 - GravityDirectionY float64 - GravityDirectionZ float64 - GravityMagnitude float64 - Resolution int // Number of voxels on the longest axis of 3D model AABB. - NonlinearConsidered bool // If true, nonlinear finite elements are generated. - ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. + PathStl string // Input STL file. + PathResultWithPlaceholder string // Result file, consumable by ABAQUS or CalculiX. Must include "#" character as placeholder for layer number. + PathResultInfo string // Result details and info. + MassDensity float64 + YoungModulus float64 + PoissonRatio float64 + GravityDirectionX float64 + GravityDirectionY float64 + GravityDirectionZ float64 + GravityMagnitude float64 + Resolution int // Number of voxels on the longest axis of 3D model AABB. + NonlinearConsidered bool // If true, nonlinear finite elements are generated. + ExactSurfaceConsidered bool // If true, surface is approximated by tetrahedral finite elements. } type Restraint struct { @@ -143,7 +143,7 @@ func main() { // The first few layers are ignored. for z := 3; z <= voxelsZ; z++ { err := m.WriteInpLayers( - strings.Replace(specs.PathResult, "#", fmt.Sprintf("%d", z), 1), + strings.Replace(specs.PathResultWithPlaceholder, "#", fmt.Sprintf("%d", z), 1), 0, z, // Note that the start layer is included, the end layer is excluded. float32(specs.MassDensity), float32(specs.YoungModulus), float32(specs.PoissonRatio), restraintsPrintFloor(m), diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go index f095ae3b8..e9dee788f 100644 --- a/examples/finite_elements_print3d/main_test.go +++ b/examples/finite_elements_print3d/main_test.go @@ -32,19 +32,19 @@ func Test_main(t *testing.T) { name: "teapot", pathSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "teapot.stl"), - PathResult: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), - MassDensity: 7.85e-9, - YoungModulus: 210000, - PoissonRatio: 0.3, - GravityDirectionX: 0, - GravityDirectionY: 0, - GravityDirectionZ: +1, // SLA 3D print is usually done upside down. - GravityMagnitude: 9810, - Resolution: 50, - NonlinearConsidered: false, - ExactSurfaceConsidered: true, + PathStl: filepath.Join("..", "..", "files", "teapot.stl"), + PathResultWithPlaceholder: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), + PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), + MassDensity: 7.85e-9, + YoungModulus: 210000, + PoissonRatio: 0.3, + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: +1, // SLA 3D print is usually done upside down. + GravityMagnitude: 9810, + Resolution: 50, + NonlinearConsidered: false, + ExactSurfaceConsidered: true, }, }, } From e2ffa51617136ec85c7bf0ebb39c70dcd0263bbd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 09:14:23 +0330 Subject: [PATCH 750/775] Comment --- examples/finite_elements_print3d/main_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go index e9dee788f..296a0e847 100644 --- a/examples/finite_elements_print3d/main_test.go +++ b/examples/finite_elements_print3d/main_test.go @@ -40,8 +40,8 @@ func Test_main(t *testing.T) { PoissonRatio: 0.3, GravityDirectionX: 0, GravityDirectionY: 0, - GravityDirectionZ: +1, // SLA 3D print is usually done upside down. - GravityMagnitude: 9810, + GravityDirectionZ: +1, // SLA 3D print is usually done upside down. + GravityMagnitude: 9810, // mm unit. Resolution: 50, NonlinearConsidered: false, ExactSurfaceConsidered: true, From a91185092414b66754713407d50f147f051243ec Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 09:22:29 +0330 Subject: [PATCH 751/775] Remove unnecessary statements --- sdf/finiteelements/mesh/fem.go | 25 ++++++++++------------- sdf/finiteelements/mesh/restraint_load.go | 8 +------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 4d7732a2e..5d0cc4802 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -209,20 +209,17 @@ func restraintSetup(m *Fem, restraints []*Restraint) []*Restraint { func loadSetup(m *Fem, loads []*Load) []*Load { // Figure out voxel for each. for _, l := range loads { - // Set voxel, if not already set. - // If voxel is already set, it means the caller has decided about voxel. - if l.voxel.X == -1 && l.voxel.Y == -1 && l.voxel.Z == -1 { - voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{l.Location}) - if len(voxels) < 1 { - log.Fatalln("no voxel is intersecting with the point load") - } - l.voxel = voxels[0] - closestVertex, closestVoxel := m.Locate(l.Location) - l.voxel = closestVoxel - l.nodeREF = closestVertex - if voxels[0].X != closestVoxel.X && voxels[0].Y != closestVoxel.Y && voxels[0].Z != closestVoxel.Z { - fmt.Println("m.VoxelsIntersecting() != m.Locate()") - } + voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{l.Location}) + if len(voxels) < 1 { + log.Fatalln("no voxel is intersecting with the point load") + } + + closestVertex, closestVoxel := m.Locate(l.Location) + l.voxel = closestVoxel + l.nodeREF = closestVertex + + if voxels[0].X != closestVoxel.X && voxels[0].Y != closestVoxel.Y && voxels[0].Z != closestVoxel.Z { + fmt.Println("just a double-check: m.VoxelsIntersecting() != m.Locate()") } } return loads diff --git a/sdf/finiteelements/mesh/restraint_load.go b/sdf/finiteelements/mesh/restraint_load.go index 97385ddfa..1b437ff47 100644 --- a/sdf/finiteelements/mesh/restraint_load.go +++ b/sdf/finiteelements/mesh/restraint_load.go @@ -37,6 +37,7 @@ func NewRestraint(location v3.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint } } +// All the nodes inside the input voxel will be considered as restraint. func NewRestraintByVoxel(voxel v3i.Vec, isFixedX, isFixedY, isFixedZ bool) *Restraint { return &Restraint{ IsFixedX: isFixedX, @@ -53,10 +54,3 @@ func NewLoad(location v3.Vec, magnitude v3.Vec) *Load { voxel: v3i.Vec{X: -1, Y: -1, Z: -1}, // We depend on -1 value to see if voxel is valid. } } - -func NewLoadByVoxel(voxel v3i.Vec, magnitude v3.Vec) *Load { - return &Load{ - Magnitude: magnitude, - voxel: voxel, - } -} From 9cb0f88a85a8f42cbc81d9b9aada010ec6a98ddc Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 11:29:32 +0330 Subject: [PATCH 752/775] New API: FEA log file --- examples/finite_elements/main.go | 1 + examples/finite_elements_print3d/main.go | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 257051e88..abdb392a4 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -26,6 +26,7 @@ type Specs struct { PathRestraintPoints string // File containing point restraints. PathResult string // Result file, consumable by ABAQUS or CalculiX. PathResultInfo string // Result details and info. + PathLogFea string // Log file of FEA. MassDensity float64 YoungModulus float64 PoissonRatio float64 diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 1b7fb61ca..a88a4c956 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -26,6 +26,7 @@ type Specs struct { PathStl string // Input STL file. PathResultWithPlaceholder string // Result file, consumable by ABAQUS or CalculiX. Must include "#" character as placeholder for layer number. PathResultInfo string // Result details and info. + PathLogFea string // Log file of FEA. MassDensity float64 YoungModulus float64 PoissonRatio float64 From d567fdbc150079537b6458c3a7ebf59f51cb25dd Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 11:55:15 +0330 Subject: [PATCH 753/775] Fatal log: inconsistent voxel for point load --- sdf/finiteelements/mesh/fem.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 5d0cc4802..5dd82a442 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -1,7 +1,6 @@ package mesh import ( - "fmt" "log" "math" @@ -215,12 +214,13 @@ func loadSetup(m *Fem, loads []*Load) []*Load { } closestVertex, closestVoxel := m.Locate(l.Location) - l.voxel = closestVoxel - l.nodeREF = closestVertex if voxels[0].X != closestVoxel.X && voxels[0].Y != closestVoxel.Y && voxels[0].Z != closestVoxel.Z { - fmt.Println("just a double-check: m.VoxelsIntersecting() != m.Locate()") + log.Fatalln("point load is not in a valid/consistent voxel: m.VoxelsIntersecting() != m.Locate()") } + + l.voxel = closestVoxel + l.nodeREF = closestVertex } return loads } From c76f2b0466eff966d51b1e5cd00c1d483eef462d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 11:59:48 +0330 Subject: [PATCH 754/775] Comment --- sdf/finiteelements/mesh/fem.go | 1 + 1 file changed, 1 insertion(+) diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 5dd82a442..677564ae4 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -194,6 +194,7 @@ func restraintSetup(m *Fem, restraints []*Restraint) []*Restraint { for _, r := range restraints { // Set voxel, if not already set. // If voxel is already set, it means the caller has decided about voxel. + // It means all the nodes inside the voxel will be restraint. if r.voxel.X == -1 && r.voxel.Y == -1 && r.voxel.Z == -1 { voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{r.Location}) if len(voxels) < 1 { From 3ca2f11443cad2e3c9b104054cf94b3932d6c3c8 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 12:12:45 +0330 Subject: [PATCH 755/775] Test: new API --- examples/finite_elements/main_test.go | 4 ++++ examples/finite_elements_print3d/main.go | 1 + examples/finite_elements_print3d/main_test.go | 2 ++ 3 files changed, 7 insertions(+) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index aa9a15659..1ae17407c 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -39,6 +39,7 @@ func Test_main(t *testing.T) { PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), + PathLogFea: filepath.Join(os.TempDir(), "bms-FEA-log.txt"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -105,6 +106,7 @@ func Test_main(t *testing.T) { PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), + PathLogFea: filepath.Join(os.TempDir(), "bmc-FEA-log.txt"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -150,6 +152,7 @@ func Test_main(t *testing.T) { PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), + PathLogFea: filepath.Join(os.TempDir(), "bmp-FEA-log.txt"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -195,6 +198,7 @@ func Test_main(t *testing.T) { PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), + PathLogFea: filepath.Join(os.TempDir(), "bmi-FEA-log.txt"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index a88a4c956..b4bdba318 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -27,6 +27,7 @@ type Specs struct { PathResultWithPlaceholder string // Result file, consumable by ABAQUS or CalculiX. Must include "#" character as placeholder for layer number. PathResultInfo string // Result details and info. PathLogFea string // Log file of FEA. + LayerToStartFea int // FEA will be done after this layer. MassDensity float64 YoungModulus float64 PoissonRatio float64 diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go index 296a0e847..c6f4ab75f 100644 --- a/examples/finite_elements_print3d/main_test.go +++ b/examples/finite_elements_print3d/main_test.go @@ -35,6 +35,8 @@ func Test_main(t *testing.T) { PathStl: filepath.Join("..", "..", "files", "teapot.stl"), PathResultWithPlaceholder: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), + PathLogFea: filepath.Join(os.TempDir(), "teapot-FEA-log.txt"), + LayerToStartFea: 3, MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, From 29321268eab129156ba06a9c67dba62477915502 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 12:20:06 +0330 Subject: [PATCH 756/775] Layer to start FEA --- examples/finite_elements_print3d/main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index b4bdba318..d6674202a 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -138,12 +138,12 @@ func main() { // Generate finite elements layer-by-layer. // Applicable to 3D print analysis that is done layer-by-layer. - if voxelsZ < 8 { - log.Fatalf("not enough voxel layers along the Z axis %d", voxelsZ) + if voxelsZ < specs.LayerToStartFea+3 { + log.Fatalf("not enough voxel layers along the Z axis %d < %d", voxelsZ, specs.LayerToStartFea+3) } // The first few layers are ignored. - for z := 3; z <= voxelsZ; z++ { + for z := specs.LayerToStartFea; z <= voxelsZ; z++ { err := m.WriteInpLayers( strings.Replace(specs.PathResultWithPlaceholder, "#", fmt.Sprintf("%d", z), 1), 0, z, // Note that the start layer is included, the end layer is excluded. From 8473e7a6ef23bbccd4cebe6b962b79e249ff42b4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 12:26:27 +0330 Subject: [PATCH 757/775] Delete unneeded API: FEA log file --- examples/finite_elements/main.go | 1 - examples/finite_elements/main_test.go | 4 ---- examples/finite_elements_print3d/main.go | 1 - examples/finite_elements_print3d/main_test.go | 1 - 4 files changed, 7 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index abdb392a4..257051e88 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -26,7 +26,6 @@ type Specs struct { PathRestraintPoints string // File containing point restraints. PathResult string // Result file, consumable by ABAQUS or CalculiX. PathResultInfo string // Result details and info. - PathLogFea string // Log file of FEA. MassDensity float64 YoungModulus float64 PoissonRatio float64 diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 1ae17407c..aa9a15659 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -39,7 +39,6 @@ func Test_main(t *testing.T) { PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), - PathLogFea: filepath.Join(os.TempDir(), "bms-FEA-log.txt"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -106,7 +105,6 @@ func Test_main(t *testing.T) { PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), - PathLogFea: filepath.Join(os.TempDir(), "bmc-FEA-log.txt"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -152,7 +150,6 @@ func Test_main(t *testing.T) { PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), - PathLogFea: filepath.Join(os.TempDir(), "bmp-FEA-log.txt"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -198,7 +195,6 @@ func Test_main(t *testing.T) { PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), - PathLogFea: filepath.Join(os.TempDir(), "bmi-FEA-log.txt"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index d6674202a..901b8e0cc 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -26,7 +26,6 @@ type Specs struct { PathStl string // Input STL file. PathResultWithPlaceholder string // Result file, consumable by ABAQUS or CalculiX. Must include "#" character as placeholder for layer number. PathResultInfo string // Result details and info. - PathLogFea string // Log file of FEA. LayerToStartFea int // FEA will be done after this layer. MassDensity float64 YoungModulus float64 diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go index c6f4ab75f..ea3415c23 100644 --- a/examples/finite_elements_print3d/main_test.go +++ b/examples/finite_elements_print3d/main_test.go @@ -35,7 +35,6 @@ func Test_main(t *testing.T) { PathStl: filepath.Join("..", "..", "files", "teapot.stl"), PathResultWithPlaceholder: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), - PathLogFea: filepath.Join(os.TempDir(), "teapot-FEA-log.txt"), LayerToStartFea: 3, MassDensity: 7.85e-9, YoungModulus: 210000, From 280e2d11e8dede9276bb9be478d48963553ee8ed Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Tue, 5 Sep 2023 12:33:12 +0330 Subject: [PATCH 758/775] Fix log --- examples/finite_elements_print3d/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 901b8e0cc..a08b9fe81 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -155,7 +155,7 @@ func main() { if err != nil { log.Fatalf(err.Error()) } - fmt.Printf("Finite elements are generated from layer 0 to layer %v out of %v total.\n", z, voxelsZ-1) + fmt.Printf("Finite elements are generated from layer 0 to layer %v out of %v total.\n", z, voxelsZ) } if err != nil { From e2a16fca77e5b15cc86c41e23901c4322d5bfa3c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Mon, 11 Sep 2023 16:52:26 +0330 Subject: [PATCH 759/775] Tensile strength --- examples/finite_elements_print3d/main.go | 1 + examples/finite_elements_print3d/main_test.go | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index a08b9fe81..9d7a63da7 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -30,6 +30,7 @@ type Specs struct { MassDensity float64 YoungModulus float64 PoissonRatio float64 + TensileStrength float64 GravityDirectionX float64 GravityDirectionY float64 GravityDirectionZ float64 diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go index ea3415c23..a8af014c6 100644 --- a/examples/finite_elements_print3d/main_test.go +++ b/examples/finite_elements_print3d/main_test.go @@ -18,8 +18,6 @@ import ( "testing" ) -// Benchmark reference: -// https://github.com/calculix/CalculiX-Examples/tree/master/NonLinear/Sections func Test_main(t *testing.T) { tests := []struct { skip bool From 24f95299682a7caefa3c87704434148ff98b07e3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 13 Sep 2023 13:44:52 +0330 Subject: [PATCH 760/775] Remove unneeded field --- examples/finite_elements_print3d/main.go | 1 - sdf/finiteelements/mesh/fem.go | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 9d7a63da7..a08b9fe81 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -30,7 +30,6 @@ type Specs struct { MassDensity float64 YoungModulus float64 PoissonRatio float64 - TensileStrength float64 GravityDirectionX float64 GravityDirectionY float64 GravityDirectionZ float64 diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 677564ae4..fe8ae5cd6 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -222,6 +222,7 @@ func loadSetup(m *Fem, loads []*Load) []*Load { l.voxel = closestVoxel l.nodeREF = closestVertex + log.Printf("point load coordinates %f, %f, %f\n", l.nodeREF.X, l.nodeREF.Y, l.nodeREF.Z) } return loads } From 9e1435047c58239167dde074287ffcd615f32b54 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 13 Sep 2023 13:45:59 +0330 Subject: [PATCH 761/775] Revert "Remove unneeded field" This reverts commit 24f95299682a7caefa3c87704434148ff98b07e3. --- examples/finite_elements_print3d/main.go | 1 + sdf/finiteelements/mesh/fem.go | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index a08b9fe81..9d7a63da7 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -30,6 +30,7 @@ type Specs struct { MassDensity float64 YoungModulus float64 PoissonRatio float64 + TensileStrength float64 GravityDirectionX float64 GravityDirectionY float64 GravityDirectionZ float64 diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index fe8ae5cd6..677564ae4 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -222,7 +222,6 @@ func loadSetup(m *Fem, loads []*Load) []*Load { l.voxel = closestVoxel l.nodeREF = closestVertex - log.Printf("point load coordinates %f, %f, %f\n", l.nodeREF.X, l.nodeREF.Y, l.nodeREF.Z) } return loads } From 93b5460c26abc717df2d337cc31fb2b37c7e3c55 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Wed, 13 Sep 2023 13:50:30 +0330 Subject: [PATCH 762/775] Delete unneeded field --- examples/finite_elements_print3d/main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 9d7a63da7..a08b9fe81 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -30,7 +30,6 @@ type Specs struct { MassDensity float64 YoungModulus float64 PoissonRatio float64 - TensileStrength float64 GravityDirectionX float64 GravityDirectionY float64 GravityDirectionZ float64 From 0a1d1be304433355d3e43bc2d0b94321b7b2f5e2 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 15 Sep 2023 12:02:17 +0330 Subject: [PATCH 763/775] Rename and delete unneeded --- examples/finite_elements/main.go | 12 +++++------ examples/finite_elements/main_test.go | 8 +++---- examples/finite_elements_print3d/main.go | 21 +++++++++---------- examples/finite_elements_print3d/main_test.go | 3 +-- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index 257051e88..f84def957 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -25,7 +25,7 @@ type Specs struct { PathLoadPoints string // File containing point loads. PathRestraintPoints string // File containing point restraints. PathResult string // Result file, consumable by ABAQUS or CalculiX. - PathResultInfo string // Result details and info. + PathReport string // Report some details after finite elements are generated. MassDensity float64 YoungModulus float64 PoissonRatio float64 @@ -61,7 +61,7 @@ type Component struct { VoxelCount int } -type ResultInfo struct { +type Report struct { VoxelsX int VoxelsY int VoxelsZ int @@ -136,7 +136,7 @@ func main() { m, voxelsX, voxelsY, voxelsZ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) components := m.Components() - info := ResultInfo{ + report := Report{ VoxelsX: voxelsX, VoxelsY: voxelsY, VoxelsZ: voxelsZ, @@ -144,14 +144,14 @@ func main() { Components: make([]Component, len(components)), } for i, component := range components { - info.Components[i] = Component{VoxelCount: component.VoxelCount()} + report.Components[i] = Component{VoxelCount: component.VoxelCount()} } - jsonData, err = json.MarshalIndent(info, "", " ") + jsonData, err = json.MarshalIndent(report, "", " ") if err != nil { log.Fatalf(err.Error()) } - err = os.WriteFile(specs.PathResultInfo, jsonData, 0644) + err = os.WriteFile(specs.PathReport, jsonData, 0644) if err != nil { log.Fatalf(err.Error()) } diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index aa9a15659..07dd07c28 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -38,7 +38,7 @@ func Test_main(t *testing.T) { PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bms-result-info.json"), + PathReport: filepath.Join(os.TempDir(), "bms-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -104,7 +104,7 @@ func Test_main(t *testing.T) { PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmc-result-info.json"), + PathReport: filepath.Join(os.TempDir(), "bmc-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -149,7 +149,7 @@ func Test_main(t *testing.T) { PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmp-result-info.json"), + PathReport: filepath.Join(os.TempDir(), "bmp-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -194,7 +194,7 @@ func Test_main(t *testing.T) { PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "bmi-result-info.json"), + PathReport: filepath.Join(os.TempDir(), "bmi-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index a08b9fe81..7d8e98d14 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -25,8 +25,7 @@ import ( type Specs struct { PathStl string // Input STL file. PathResultWithPlaceholder string // Result file, consumable by ABAQUS or CalculiX. Must include "#" character as placeholder for layer number. - PathResultInfo string // Result details and info. - LayerToStartFea int // FEA will be done after this layer. + PathReport string // Report some details after finite elements are generated. MassDensity float64 YoungModulus float64 PoissonRatio float64 @@ -61,7 +60,7 @@ type Component struct { VoxelCount int } -type ResultInfo struct { +type Report struct { VoxelsX int VoxelsY int VoxelsZ int @@ -114,7 +113,7 @@ func main() { m, voxelsX, voxelsY, voxelsZ := mesh.NewFem(inSdf, render.NewMarchingCubesFeUniform(specs.Resolution, order, shape)) components := m.Components() - info := ResultInfo{ + report := Report{ VoxelsX: voxelsX, VoxelsY: voxelsY, VoxelsZ: voxelsZ, @@ -122,14 +121,14 @@ func main() { Components: make([]Component, len(components)), } for i, component := range components { - info.Components[i] = Component{VoxelCount: component.VoxelCount()} + report.Components[i] = Component{VoxelCount: component.VoxelCount()} } - jsonData, err = json.MarshalIndent(info, "", " ") + jsonData, err = json.MarshalIndent(report, "", " ") if err != nil { log.Fatalf(err.Error()) } - err = os.WriteFile(specs.PathResultInfo, jsonData, 0644) + err = os.WriteFile(specs.PathReport, jsonData, 0644) if err != nil { log.Fatalf(err.Error()) } @@ -137,12 +136,12 @@ func main() { // Generate finite elements layer-by-layer. // Applicable to 3D print analysis that is done layer-by-layer. - if voxelsZ < specs.LayerToStartFea+3 { - log.Fatalf("not enough voxel layers along the Z axis %d < %d", voxelsZ, specs.LayerToStartFea+3) + if voxelsZ < 3 { + log.Fatalf("not enough voxel layers along the Z axis %d < %d", voxelsZ, 3) } - // The first few layers are ignored. - for z := specs.LayerToStartFea; z <= voxelsZ; z++ { + // All layers are considered. + for z := 0; z <= voxelsZ; z++ { err := m.WriteInpLayers( strings.Replace(specs.PathResultWithPlaceholder, "#", fmt.Sprintf("%d", z), 1), 0, z, // Note that the start layer is included, the end layer is excluded. diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go index a8af014c6..80c87ad20 100644 --- a/examples/finite_elements_print3d/main_test.go +++ b/examples/finite_elements_print3d/main_test.go @@ -32,8 +32,7 @@ func Test_main(t *testing.T) { specs: Specs{ PathStl: filepath.Join("..", "..", "files", "teapot.stl"), PathResultWithPlaceholder: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), - PathResultInfo: filepath.Join(os.TempDir(), "teapot-result-info.json"), - LayerToStartFea: 3, + PathReport: filepath.Join(os.TempDir(), "teapot-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, From bdef1e1236042e7df9c662f1de541eaca9238957 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 15 Sep 2023 13:54:34 +0330 Subject: [PATCH 764/775] Fields order --- examples/finite_elements_print3d/main.go | 2 +- examples/finite_elements_print3d/main_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 7d8e98d14..0e94b0ed7 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -23,9 +23,9 @@ import ( ) type Specs struct { - PathStl string // Input STL file. PathResultWithPlaceholder string // Result file, consumable by ABAQUS or CalculiX. Must include "#" character as placeholder for layer number. PathReport string // Report some details after finite elements are generated. + PathStl string // Input STL file. MassDensity float64 YoungModulus float64 PoissonRatio float64 diff --git a/examples/finite_elements_print3d/main_test.go b/examples/finite_elements_print3d/main_test.go index 80c87ad20..2f6a4d0d0 100644 --- a/examples/finite_elements_print3d/main_test.go +++ b/examples/finite_elements_print3d/main_test.go @@ -30,9 +30,9 @@ func Test_main(t *testing.T) { name: "teapot", pathSpecs: filepath.Join(os.TempDir(), "teapot-specs.json"), specs: Specs{ - PathStl: filepath.Join("..", "..", "files", "teapot.stl"), PathResultWithPlaceholder: filepath.Join(os.TempDir(), "teapot-result-layer0-to-layer#.inp"), PathReport: filepath.Join(os.TempDir(), "teapot-report.json"), + PathStl: filepath.Join("..", "..", "files", "teapot.stl"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, From c2591986a4e5c447b58afd537c3ebc7fc11e3c10 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 15 Sep 2023 13:57:31 +0330 Subject: [PATCH 765/775] Fields order --- examples/finite_elements/main.go | 4 ++-- examples/finite_elements/main_test.go | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/finite_elements/main.go b/examples/finite_elements/main.go index f84def957..2db3d4c2b 100644 --- a/examples/finite_elements/main.go +++ b/examples/finite_elements/main.go @@ -21,11 +21,11 @@ import ( ) type Specs struct { + PathResult string // Result file, consumable by ABAQUS or CalculiX. + PathReport string // Report some details after finite elements are generated. PathStl string // Input STL file. PathLoadPoints string // File containing point loads. PathRestraintPoints string // File containing point restraints. - PathResult string // Result file, consumable by ABAQUS or CalculiX. - PathReport string // Report some details after finite elements are generated. MassDensity float64 YoungModulus float64 PoissonRatio float64 diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 07dd07c28..4e51cb05c 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -34,11 +34,11 @@ func Test_main(t *testing.T) { name: "benchmarkSquare", pathSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), specs: Specs{ + PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), + PathReport: filepath.Join(os.TempDir(), "bms-report.json"), PathStl: filepath.Join("..", "..", "files", "benchmark-square.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "bms-load-points.json"), PathRestraintPoints: filepath.Join(os.TempDir(), "bms-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bms-result.inp"), - PathReport: filepath.Join(os.TempDir(), "bms-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -100,11 +100,11 @@ func Test_main(t *testing.T) { name: "benchmarkCircle", pathSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), specs: Specs{ + PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), + PathReport: filepath.Join(os.TempDir(), "bmc-report.json"), PathStl: filepath.Join("..", "..", "files", "benchmark-circle.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "bmc-load-points.json"), PathRestraintPoints: filepath.Join(os.TempDir(), "bmc-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmc-result.inp"), - PathReport: filepath.Join(os.TempDir(), "bmc-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -145,11 +145,11 @@ func Test_main(t *testing.T) { name: "benchmarkPipe", pathSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), specs: Specs{ + PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), + PathReport: filepath.Join(os.TempDir(), "bmp-report.json"), PathStl: filepath.Join("..", "..", "files", "benchmark-pipe.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "bmp-load-points.json"), PathRestraintPoints: filepath.Join(os.TempDir(), "bmp-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmp-result.inp"), - PathReport: filepath.Join(os.TempDir(), "bmp-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, @@ -190,11 +190,11 @@ func Test_main(t *testing.T) { name: "benchmarkI", pathSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), specs: Specs{ + PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), + PathReport: filepath.Join(os.TempDir(), "bmi-report.json"), PathStl: filepath.Join("..", "..", "files", "benchmark-I.stl"), PathLoadPoints: filepath.Join(os.TempDir(), "bmi-load-points.json"), PathRestraintPoints: filepath.Join(os.TempDir(), "bmi-restraint-points.json"), - PathResult: filepath.Join(os.TempDir(), "bmi-result.inp"), - PathReport: filepath.Join(os.TempDir(), "bmi-report.json"), MassDensity: 7.85e-9, YoungModulus: 210000, PoissonRatio: 0.3, From f6dcdcdc968c396562be01960be1efd97246d29c Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 15 Sep 2023 14:39:08 +0330 Subject: [PATCH 766/775] Allow the same start & end layer --- sdf/finiteelements/mesh/inp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdf/finiteelements/mesh/inp.go b/sdf/finiteelements/mesh/inp.go index b5829157a..701c5c942 100644 --- a/sdf/finiteelements/mesh/inp.go +++ b/sdf/finiteelements/mesh/inp.go @@ -170,7 +170,7 @@ func (inp *Inp) Write() error { func (inp *Inp) writeHeader(f *os.File) error { _, _, layersZ := inp.Mesh.Size() - if 0 <= inp.LayerStart && inp.LayerStart < inp.LayerEnd && inp.LayerEnd <= layersZ { + if 0 <= inp.LayerStart && inp.LayerStart <= inp.LayerEnd && inp.LayerEnd <= layersZ { // Good. } else { return fmt.Errorf("start or end layer is beyond range") From ad7dcd46d95ea1c5b8b56f135e710b28fc2201d7 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Fri, 15 Sep 2023 15:37:58 +0330 Subject: [PATCH 767/775] Fix start layer --- examples/finite_elements_print3d/main.go | 4 ++-- sdf/finiteelements/mesh/inp.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/finite_elements_print3d/main.go b/examples/finite_elements_print3d/main.go index 0e94b0ed7..972a341ae 100644 --- a/examples/finite_elements_print3d/main.go +++ b/examples/finite_elements_print3d/main.go @@ -140,8 +140,8 @@ func main() { log.Fatalf("not enough voxel layers along the Z axis %d < %d", voxelsZ, 3) } - // All layers are considered. - for z := 0; z <= voxelsZ; z++ { + // Skip 0 and start from 1, to be sensible. + for z := 1; z <= voxelsZ; z++ { err := m.WriteInpLayers( strings.Replace(specs.PathResultWithPlaceholder, "#", fmt.Sprintf("%d", z), 1), 0, z, // Note that the start layer is included, the end layer is excluded. diff --git a/sdf/finiteelements/mesh/inp.go b/sdf/finiteelements/mesh/inp.go index 701c5c942..b5829157a 100644 --- a/sdf/finiteelements/mesh/inp.go +++ b/sdf/finiteelements/mesh/inp.go @@ -170,7 +170,7 @@ func (inp *Inp) Write() error { func (inp *Inp) writeHeader(f *os.File) error { _, _, layersZ := inp.Mesh.Size() - if 0 <= inp.LayerStart && inp.LayerStart <= inp.LayerEnd && inp.LayerEnd <= layersZ { + if 0 <= inp.LayerStart && inp.LayerStart < inp.LayerEnd && inp.LayerEnd <= layersZ { // Good. } else { return fmt.Errorf("start or end layer is beyond range") From df1526d986bc4ed1b881356afd35a6f44be91b6d Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 16 Sep 2023 16:35:19 +0330 Subject: [PATCH 768/775] Log --- sdf/finiteelements/mesh/fem.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 677564ae4..495588e28 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -198,7 +198,7 @@ func restraintSetup(m *Fem, restraints []*Restraint) []*Restraint { if r.voxel.X == -1 && r.voxel.Y == -1 && r.voxel.Z == -1 { voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{r.Location}) if len(voxels) < 1 { - log.Fatalln("no voxel is intersecting with the point restraint") + log.Fatalf("no voxel is intersecting with the point restraint: %f, %f, %f\n", r.Location.X, r.Location.Y, r.Location.Z) } r.voxel = voxels[0] } @@ -211,7 +211,7 @@ func loadSetup(m *Fem, loads []*Load) []*Load { for _, l := range loads { voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{l.Location}) if len(voxels) < 1 { - log.Fatalln("no voxel is intersecting with the point load") + log.Fatalf("no voxel is intersecting with the point load: %f, %f, %f\n", l.Location.X, l.Location.Y, l.Location.Z) } closestVertex, closestVoxel := m.Locate(l.Location) From d7fa8c10b51b20ff596f6ec6e9b4eaf16c5c8966 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 16 Sep 2023 17:56:59 +0330 Subject: [PATCH 769/775] Test with new func to debug --- sdf/finiteelements/buffer/voxel.go | 31 ++++++++++++++++++++++++++++++ sdf/finiteelements/mesh/fem.go | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/sdf/finiteelements/buffer/voxel.go b/sdf/finiteelements/buffer/voxel.go index 8b37b5e9e..5fd1a0c33 100644 --- a/sdf/finiteelements/buffer/voxel.go +++ b/sdf/finiteelements/buffer/voxel.go @@ -161,6 +161,37 @@ func DoesIntersect(aMin, aMax, bMin, bMax v3.Vec) bool { return true } +// Return all the voxels that are intersecting with a single point. +func (vg *VoxelGrid) VoxelsIntersectingWithPoint(point v3.Vec) []v3i.Vec { + var intersectingVoxels []v3i.Vec + + // iterate over all the voxels + for i, voxel := range vg.Voxels { + // check if the voxel intersects with the bounding box + if !DoesIntersectPointWithBox(point, voxel.Min, voxel.Max) { + continue + } + + // convert the 1D index to a 3D index + x, y, z := vg.index1Dto3D(i) + + intersectingVoxels = append(intersectingVoxels, v3i.Vec{X: x, Y: y, Z: z}) + } + + return intersectingVoxels +} + +// Does a point and a bounding box intersect with each other? +func DoesIntersectPointWithBox(point, boxMin, boxMax v3.Vec) bool { + if point.X < boxMin.X || point.Y < boxMin.Y || point.Z < boxMin.Z { + return false + } + if point.X > boxMax.X || point.Y > boxMax.Y || point.Z > boxMax.Z { + return false + } + return true +} + // To iterate over all voxels and get elements inside each voxel and do stuff with them. func (vg *VoxelGrid) Iterate(f func(int, int, int, []*Element)) { for z := 0; z < vg.Len.Z; z++ { diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index 495588e28..aa08d6473 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -196,7 +196,7 @@ func restraintSetup(m *Fem, restraints []*Restraint) []*Restraint { // If voxel is already set, it means the caller has decided about voxel. // It means all the nodes inside the voxel will be restraint. if r.voxel.X == -1 && r.voxel.Y == -1 && r.voxel.Z == -1 { - voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{r.Location}) + voxels := m.IBuff.Grid.VoxelsIntersectingWithPoint(r.Location) if len(voxels) < 1 { log.Fatalf("no voxel is intersecting with the point restraint: %f, %f, %f\n", r.Location.X, r.Location.Y, r.Location.Z) } From 9802d867aac236b2c33d28a0550a8f430e268bbf Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 16 Sep 2023 22:07:34 +0330 Subject: [PATCH 770/775] New test case --- examples/finite_elements/main_test.go | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 4e51cb05c..2fe525e77 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -13,6 +13,7 @@ package main import ( "encoding/json" + "math" "os" "path/filepath" "testing" @@ -29,6 +30,39 @@ func Test_main(t *testing.T) { loads []Load // If load is zero, gravity would be the dominant force. restraints []Restraint }{ + { + skip: false, + name: "teapot", + pathSpecs: filepath.Join(os.TempDir(), "specs.json"), + specs: Specs{ + PathResult: filepath.Join(os.TempDir(), "result.inp"), + PathReport: filepath.Join(os.TempDir(), "report.json"), + PathStl: filepath.Join("..", "..", "files", "teapot.stl"), // Valid STL, Unit: mm + PathLoadPoints: filepath.Join(os.TempDir(), "load-points.json"), + PathRestraintPoints: filepath.Join(os.TempDir(), "restraint-points.json"), + MassDensity: 1130 * math.Pow(10, -12), // (N*s2/mm4) // Assumed: 1.13 g/cm3 + YoungModulus: 1.6 * 1000, // MPa (N/mm2) + PoissonRatio: 0.3, // Unitless. + GravityDirectionX: 0, + GravityDirectionY: 0, + GravityDirectionZ: -1, + GravityMagnitude: 9810, // mm/s2 + GravityIsNeeded: false, + Resolution: 50, + NonlinearConsidered: false, + ExactSurfaceConsidered: true, + }, + loads: []Load{ + {LocX: -7.7018147506213062, LocY: -0.4793329364029888, LocZ: 5.4655784011739659, MagX: -70.381474830032147, MagY: -174.42493975029208, MagZ: 59.390099907428898}, + {LocX: -0.011008272390835461, LocY: -0.7768798803556729, LocZ: 8.0940818810755175, MagX: -7.1696819796276845, MagY: -157.24707657594607, MagZ: -122.86811489950169}, + {LocX: 7.7771501865767299, LocY: -0.44676917365822177, LocZ: 6.1957182567021745, MagX: 8.5251191596139506, MagY: -198.29032531361477, MagZ: 18.196364257032524}, + }, + restraints: []Restraint{ + {LocX: 2.6121906631017695, LocY: 0.20348199936959829, LocZ: 0.050483960817894413, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: -1.3968227044257533, LocY: -2.035934011608322, LocZ: 0.04909315835598238, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + {LocX: -1.8197506822193277, LocY: 2.2580011513606717, LocZ: 0.064527793304306025, IsFixedX: true, IsFixedY: true, IsFixedZ: true}, + }, + }, { skip: false, name: "benchmarkSquare", From ce28856d91a3c420aeace0a3856d431b00e6046e Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 17 Sep 2023 07:15:12 +0330 Subject: [PATCH 771/775] Skip tests. Consider gravity --- examples/finite_elements/main_test.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 2fe525e77..ed0dcc33e 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -47,7 +47,7 @@ func Test_main(t *testing.T) { GravityDirectionY: 0, GravityDirectionZ: -1, GravityMagnitude: 9810, // mm/s2 - GravityIsNeeded: false, + GravityIsNeeded: true, Resolution: 50, NonlinearConsidered: false, ExactSurfaceConsidered: true, @@ -64,7 +64,7 @@ func Test_main(t *testing.T) { }, }, { - skip: false, + skip: true, name: "benchmarkSquare", pathSpecs: filepath.Join(os.TempDir(), "bms-specs.json"), specs: Specs{ @@ -130,7 +130,7 @@ func Test_main(t *testing.T) { }(), }, { - skip: false, + skip: true, name: "benchmarkCircle", pathSpecs: filepath.Join(os.TempDir(), "bmc-specs.json"), specs: Specs{ @@ -175,7 +175,7 @@ func Test_main(t *testing.T) { }, }, { - skip: false, + skip: true, name: "benchmarkPipe", pathSpecs: filepath.Join(os.TempDir(), "bmp-specs.json"), specs: Specs{ @@ -220,7 +220,7 @@ func Test_main(t *testing.T) { }, }, { - skip: false, + skip: true, name: "benchmarkI", pathSpecs: filepath.Join(os.TempDir(), "bmi-specs.json"), specs: Specs{ @@ -273,6 +273,9 @@ func Test_main(t *testing.T) { } for _, tt := range tests { + if tt.skip { + continue + } t.Run(tt.name, func(t *testing.T) { jsonData, err := json.MarshalIndent(tt.specs, "", " ") if err != nil { From 058ba81a98486a70de4b549a162d4b1513496ef0 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 17 Sep 2023 07:18:02 +0330 Subject: [PATCH 772/775] Gravity didn't fix the empty analysis results --- examples/finite_elements/main_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index ed0dcc33e..91b0e9a3f 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -47,7 +47,7 @@ func Test_main(t *testing.T) { GravityDirectionY: 0, GravityDirectionZ: -1, GravityMagnitude: 9810, // mm/s2 - GravityIsNeeded: true, + GravityIsNeeded: false, Resolution: 50, NonlinearConsidered: false, ExactSurfaceConsidered: true, From a6830c1b76d5990158abf0daa13cf6988d05dbc3 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 17 Sep 2023 07:23:16 +0330 Subject: [PATCH 773/775] Increasing resolution, fixed the empty analysis result --- examples/finite_elements/main_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/finite_elements/main_test.go b/examples/finite_elements/main_test.go index 91b0e9a3f..50f2505f1 100644 --- a/examples/finite_elements/main_test.go +++ b/examples/finite_elements/main_test.go @@ -48,7 +48,7 @@ func Test_main(t *testing.T) { GravityDirectionZ: -1, GravityMagnitude: 9810, // mm/s2 GravityIsNeeded: false, - Resolution: 50, + Resolution: 60, NonlinearConsidered: false, ExactSurfaceConsidered: true, }, From cf5056c317b15de55ed8cb1bf9ef9031ce1bb8f4 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sun, 1 Oct 2023 11:52:15 +0330 Subject: [PATCH 774/775] Avoid `tet` points too close to voxel corners. 80/20 rule. --- render/marchfehelper.go | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/render/marchfehelper.go b/render/marchfehelper.go index eabf5a6da..17150e8a6 100644 --- a/render/marchfehelper.go +++ b/render/marchfehelper.go @@ -27,11 +27,26 @@ func point(edges [12]v3.Vec, corners [8]v3.Vec, index int) v3.Vec { } // ----------------------------------------------------------------------------- -// To avoid distorted tetrahedron with non-positive Jacobian or with flat shape or with degenerate faces. -// Regradless of input values at corners, return the point at the middle of the edge. +// Tries to avoid distorted tetrahedron with +// non-positive Jacobian or with flat shape or with degenerate faces. +// Points that are close to corners, are handled differently. func mcInterpolateFE(p1, p2 v3.Vec, v1, v2, x float64) v3.Vec { - // Pick the half way point - t := 0.5 + // Try 80/20 rule. + closeToV1 := math.Abs(x-v1)/math.Abs(v2-v1) < 0.2 + closeToV2 := math.Abs(x-v1)/math.Abs(v2-v1) > 0.8 + + var t float64 + + if closeToV1 { + // Pick a point away from corner + t = 0.2 + } else if closeToV2 { + // Pick a point away from corner + t = 0.8 + } else { + // linear interpolation + t = (x - v1) / (v2 - v1) + } return v3.Vec{ X: p1.X + t*(p2.X-p1.X), From d2ccbb94162a226b84e19534026fa4478bcff8e5 Mon Sep 17 00:00:00 2001 From: Megidd Git Date: Sat, 13 Jan 2024 20:25:27 -0800 Subject: [PATCH 775/775] Fix: when load/restraint points are outside voxels --- sdf/finiteelements/mesh/fem.go | 40 ++++++++++++++++++----- sdf/finiteelements/mesh/restraint_load.go | 2 ++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/sdf/finiteelements/mesh/fem.go b/sdf/finiteelements/mesh/fem.go index aa08d6473..1a9e2f64f 100644 --- a/sdf/finiteelements/mesh/fem.go +++ b/sdf/finiteelements/mesh/fem.go @@ -100,6 +100,17 @@ func (m *Fem) Locate(location v3.Vec) (v3.Vec, v3i.Vec) { if idxZ >= m.IBuff.Grid.Len.Z { idxZ = m.IBuff.Grid.Len.Z - 1 } + // Sometimes a location on the STL geometry, is outside the voxels. + // Since the marching cubes algorithm might not be consistent with the exact STL geometry boundaries. + if idxX <= 0 { + idxX = 0 + } + if idxY <= 0 { + idxY = 0 + } + if idxZ <= 0 { + idxZ = 0 + } // Get elements in the voxel elements := m.IBuff.Grid.Get(idxX, idxY, idxZ) @@ -197,10 +208,21 @@ func restraintSetup(m *Fem, restraints []*Restraint) []*Restraint { // It means all the nodes inside the voxel will be restraint. if r.voxel.X == -1 && r.voxel.Y == -1 && r.voxel.Z == -1 { voxels := m.IBuff.Grid.VoxelsIntersectingWithPoint(r.Location) + _, closestVoxel := m.Locate(r.Location) + if len(voxels) < 1 { - log.Fatalf("no voxel is intersecting with the point restraint: %f, %f, %f\n", r.Location.X, r.Location.Y, r.Location.Z) + log.Printf("no voxel is intersecting with the point restraint: %f, %f, %f\n", r.Location.X, r.Location.Y, r.Location.Z) + log.Println("...no worries, the closest voxel will be assumed.") + r.voxel = closestVoxel + } else { + if voxels[0].X != closestVoxel.X && voxels[0].Y != closestVoxel.Y && voxels[0].Z != closestVoxel.Z { + log.Println("point restraint is outside voxel boundaries: m.VoxelsIntersecting() != m.Locate()") + log.Println("...no worries, the closest voxel will be assumed.") + r.voxel = closestVoxel + } else { + r.voxel = voxels[0] + } } - r.voxel = voxels[0] } } return restraints @@ -210,14 +232,16 @@ func loadSetup(m *Fem, loads []*Load) []*Load { // Figure out voxel for each. for _, l := range loads { voxels, _, _ := m.VoxelsIntersecting([]v3.Vec{l.Location}) - if len(voxels) < 1 { - log.Fatalf("no voxel is intersecting with the point load: %f, %f, %f\n", l.Location.X, l.Location.Y, l.Location.Z) - } - closestVertex, closestVoxel := m.Locate(l.Location) - if voxels[0].X != closestVoxel.X && voxels[0].Y != closestVoxel.Y && voxels[0].Z != closestVoxel.Z { - log.Fatalln("point load is not in a valid/consistent voxel: m.VoxelsIntersecting() != m.Locate()") + if len(voxels) < 1 { + log.Printf("no voxel is intersecting with the point load: %f, %f, %f\n", l.Location.X, l.Location.Y, l.Location.Z) + log.Println("...no worries, the closest voxel will be assumed.") + } else { + if voxels[0].X != closestVoxel.X && voxels[0].Y != closestVoxel.Y && voxels[0].Z != closestVoxel.Z { + log.Println("point load is outside voxel boundaries: m.VoxelsIntersecting() != m.Locate()") + log.Println("...no worries, the closest voxel will be assumed.") + } } l.voxel = closestVoxel diff --git a/sdf/finiteelements/mesh/restraint_load.go b/sdf/finiteelements/mesh/restraint_load.go index 1b437ff47..57bb63677 100644 --- a/sdf/finiteelements/mesh/restraint_load.go +++ b/sdf/finiteelements/mesh/restraint_load.go @@ -6,6 +6,7 @@ import ( ) // A voxel is detected that intersects with the restraint location. +// ... or that is closest to the restraint location. // Boundary is created for all the nodes inside that voxel. // This way, the stress concentration at the restraint may be alleviated by distributing it. type Restraint struct { @@ -17,6 +18,7 @@ type Restraint struct { } // A voxel is detected that intersects with the point load location. +// ... or that is closest the point load location. // A vertex inside that voxel is selected, i.e. the vertex closest to load location. // The vertex is assigned the load. // This way, point load is applied to a single node/vertex of the mesh.