~evantj/stlholo

cf49083890f416d8d9f9b44ce696950d5fca7813 — Evan Johnston 1 year, 10 days ago
init
4 files changed, 165 insertions(+), 0 deletions(-)

A go.mod
A go.sum
A main.go
A vec/vec.go
A  => go.mod +8 -0
@@ 1,8 @@
module stlholo

go 1.17

require (
	github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b
	neilpa.me/go-stl v0.0.0-20191215213742-e753f92ee45e
)

A  => go.sum +31 -0
@@ 1,31 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
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-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
neilpa.me/go-stl v0.0.0-20191215213742-e753f92ee45e h1:L+JMRASFZ2tPEyJMjCtw96fHwNxw2zlEDnM4iHubh7s=
neilpa.me/go-stl v0.0.0-20191215213742-e753f92ee45e/go.mod h1:Se6mvC5t5lD195c2kuA6ZgRto5HNi6/C5CKMfFakEus=

A  => main.go +67 -0
@@ 1,67 @@
package main

import (
	"log"
	"os"

	"neilpa.me/go-stl"
	"github.com/ajstarks/svgo"

	"stlholo/vec"

)

type Line struct {
	a [3]float32
	b [3]float32
}

const pixelsPerMM = 100
const step = 0.2

func pxFromMM(f float32) int {
	return int(f * pixelsPerMM);
}

func drawPoint(p [3]float32, s *svg.SVG) {
	s.Circle(
		pxFromMM(p[0]),
		pxFromMM(p[1]),
		pxFromMM(p[2]), "fill:none;stroke:black")
}

func drawLine(a [3]float32, b [3]float32, s *svg.SVG, lines map[Line]struct{}) {
	if _, ok := lines[Line{a, b}]; !ok { /* check if line has already been drawn */
		if pxFromMM(a[2]) == 0 && pxFromMM(b[2]) == 0 {
			s.Line(pxFromMM(a[0]), pxFromMM(a[1]), pxFromMM(b[0]), pxFromMM(b[1]), "fill:none;stroke:black")
		} else {
			for i := float32(0); i < vec.Distance(a, b); i += step {
				drawPoint(vec.Add(a, vec.Scale(vec.Dir(a, b), i)), s)
			}
		}
	}

	lines[Line{a, b}] = struct{}{}
}

func main() {
	offset := [3]float32{0, 0, 0}
	lines := make(map[Line]struct{})
	mesh, err := stl.Decode(os.Stdin)
	if err != nil {
		log.Fatal(err)
	}

	// units assumed to be mm
	w := 1000
	h := 1000
	s := svg.New(os.Stdout)
	s.Start(w, h)

	for _, face := range mesh.Faces {
		drawLine(vec.Add(face.Verts[0], offset), vec.Add(face.Verts[1], offset), s, lines);
		drawLine(vec.Add(face.Verts[1], offset), vec.Add(face.Verts[2], offset), s, lines);
		drawLine(vec.Add(face.Verts[2], offset), vec.Add(face.Verts[0], offset), s, lines);
	}
	s.End()
}

A  => vec/vec.go +59 -0
@@ 1,59 @@
package vec

import (
	"math"
)

/* This isn't really a complete set of vector ops, but it's good enough */

func Add(a [3]float32, b [3]float32) [3]float32 {
	return [3]float32 {
		a[0] + b[0],
		a[1] + b[1],
		a[2] + b[2],
	}
}

func Sub(a [3]float32, b [3]float32) [3]float32 {
	return [3]float32 {
		a[0] - b[0],
		a[1] - b[1],
		a[2] - b[2],
	}
}

func Mult(a [3]float32, b [3]float32) [3]float32 {
	return [3]float32 {
		a[0] * b[0],
		a[1] * b[1],
		a[2] * b[2],
	}
}

func Scale(a [3]float32, b float32) [3]float32 {
	return Mult(a, [3]float32{b, b, b})
}

func Div(a [3]float32, b [3]float32) [3]float32 {
	return [3]float32 {
		a[0] / b[0],
		a[1] / b[1],
		a[2] / b[2],
	}
}

func Length(v [3]float32) float32 {
	return float32(math.Sqrt(float64(v[0] * v[0] + v[1] * v[1] + v[2] * v[2])))
}

func Normal(v [3]float32) [3]float32 {
	return Scale(v, 1 / Length(v))
}

func Dir(a [3]float32, b [3]float32) [3]float32 {
	return Normal(Sub(b, a))
}

func Distance(a [3]float32, b [3]float32) float32 {
	return Length(Sub(a, b))
}