func main() { timing.StartTiming("total") timing.StartTiming("Read STL from Stdin") triangles, err := stl.Read(os.Stdin) if err != nil { log.Fatalf("stl.Read: %v", err) } timing.StopTiming("Read STL from Stdin") timing.StartTiming("STLToMesh") mesh := raster.STLToMesh(VoxelSide*MeshMultiplier, triangles) timing.StopTiming("STLToMesh") timing.StartTiming("MeshVolume") volume := triangle.MeshVolume(mesh.Triangle, 1) if volume < 0 { volume = -volume } fmt.Fprintf(os.Stderr, "Mesh volume (in mesh units): %d\n", volume) timing.StopTiming("MeshVolume") timing.StartTiming("Rasterize") vol := raster.Rasterize(mesh, VoxelSide) timing.StopTiming("Rasterize") timing.StartTiming("Optimize") Optimize(vol, 22) timing.StopTiming("Optimize") /* timing.StartTiming("Write nptl") if err = nptl.Write(os.Stdout, vol, mesh.Grid); err != nil { log.Fatalf("nptl.Write: %v", err) } v := vol.Volume() fmt.Fprintf(os.Stderr, "Volume is filled by %v%%\n", float64(v)*float64(100)/(float64(vol.N())*float64(vol.N())*float64(vol.N()))) timing.StopTiming("Write nptl") */ side := mesh.Grid.Side() vsize := surface.Vector{side, side, side} t := surface.MarchingCubes(NewVolumeField2(vol), 128, 0.8, vsize) var f *os.File if f, err = os.OpenFile("output.stl", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil { log.Fatal(err) } if err = stl.WriteBinary(f, t); err != nil { log.Fatalf("stl.Write: %v", err) } f.Close() timing.StopTiming("total") timing.PrintTimings(os.Stderr) }
func Rasterize(m Mesh, n int) volume.Space16 { scale := m.N / n vol := volume.NewSparseVolume(n) timing.StartTiming("Rasterize triangles") for index, t := range m.Triangle { triangle.AllTriangleDots(t[0], t[1], t[2], int64(scale), vol, uint16(1+(index%10))) } fmt.Fprintf(os.Stderr, "Triangle rasterization complete\n") timing.StopTiming("Rasterize triangles") timing.StartTiming("Rasterize cubes") ds := set.NewDisjoinSet() // Reserve color for outer space ds.Make() shift := 11 // Let's color cubes. for k, cube := range vol.Cubes { // Skip cubes with leaf voxels if cube != nil { continue } p := volume.K2cube(k) // If this is a cube at the edge of the space, it's a part of outer space. if p[0] == 0 || p[1] == 0 || p[2] == 0 || int(p[0]) == (1<<uint(vol.LK))-1 || int(p[1]) == (1<<uint(vol.LK))-1 || int(p[2]) == (1<<uint(vol.LK))-1 { vol.Colors[k] = uint16(shift + ds.Find(0)) continue } // Look if any neighbour has already color assigned for i := 0; i < 3; i++ { for j := -1; j <= 1; j += 2 { p2 := p p2[i] = p2[i] + j k2 := volume.Cube2k(p2) if k2 >= len(vol.Colors) { panic(fmt.Sprintf("k2: %d, len(vol.Colors): %d, len(vol.Cubes): %d, p: %v, p2: %v, k: %d", k2, len(vol.Colors), len(vol.Cubes), p, p2, k)) } if vol.Colors[k2] == 0 { continue } if vol.Colors[k] == 0 { vol.Colors[k] = vol.Colors[k2] } else { ds.Join(int(vol.Colors[k])-shift, int(vol.Colors[k2])-shift) } } } // If there's no colored neighbour, introduce a new color. if vol.Colors[k] == 0 { vol.Colors[k] = uint16(shift + ds.Make()) } } timing.StopTiming("Rasterize cubes") timing.StartTiming("Rasterize leaf voxels") // Now, we need to go through cubes which have leaf voxels for k, cube := range vol.Cubes { if cube == nil { continue } for h, val := range cube { if val != 0 { continue } p := volume.Kh2point(k, h) color := val // Look for neighbours of this leaf voxel for i := 0; i < 3; i++ { for j := -1; j <= 1; j += 2 { p2 := p p2[i] = p2[i] + j color2 := vol.Get16(g3.Node{int(p2[0]), int(p2[1]), int(p2[2])}) if int(color2) < shift { continue } if color == 0 { vol.Set16(g3.Node{int(p[0]), int(p[1]), int(p[2])}, color2) color = color2 } else { ds.Join(int(color)-shift, int(color2)-shift) } } } if color == 0 { vol.Set16(g3.Node{int(p[0]), int(p[1]), int(p[2])}, uint16(shift+ds.Make())) } } } timing.StopTiming("Rasterize leaf voxels") timing.StartTiming("Rasterize.CanonicalizeColors") // Canonicalize colors canonicalZero := uint16(shift + ds.Find(0)) for k, cube := range vol.Cubes { if cube == nil { vol.Colors[k] = uint16(shift + ds.Find(int(vol.Colors[k])-shift)) if vol.Colors[k] == canonicalZero { vol.Colors[k] = 0 } continue } for h := 0; h < len(cube); h++ { if int(cube[h]) < shift { continue } cube[h] = uint16(shift + ds.Find(int(cube[h])-shift)) if cube[h] == canonicalZero { cube[h] = 0 } } } timing.StopTiming("Rasterize.CanonicalizeColors") timing.StartTiming("Rasterize.DrawSlices") bmp := image.NewRGBA(image.Rect(0, 0, n, n)) for z := 1; z < n; z++ { if z%10 == 0 { for x := 0; x < n; x++ { for y := 0; y < n; y++ { v := vol.Get16(g3.Node{x, y, z}) if int(v) < len(colors) { bmp.Set(x, y, colors[v]) } else { bmp.Set(x, y, PinkX(int(v))) } } } f, _ := os.OpenFile(fmt.Sprintf("zban-%03d.png", z), os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0666) png.Encode(f, bmp) f.Close() } } timing.StopTiming("Rasterize.DrawSlices") fmt.Fprintf(os.Stderr, "Rasterize complete\n") return vol }