Skip to content

Instantly share code, notes, and snippets.

@DeadlySurgeon
Last active April 28, 2022 03:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DeadlySurgeon/82e881ab936a3a362beb2429384c0c3b to your computer and use it in GitHub Desktop.
Save DeadlySurgeon/82e881ab936a3a362beb2429384c0c3b to your computer and use it in GitHub Desktop.
SVG Dice Generator for Fusion Project
package main
import (
"fmt"
"math"
"reflect"
"strings"
)
// COLORBLACK ...
const COLORBLACK = "black"
const dotSize = 1.5
func main() {
height := 157.08
width := 15.0
b := &Body{
Width: width,
Height: height,
XMLNS: "http://www.w3.org/2000/svg",
children: combine(
generateLines(2, height, 6),
generateDice(height, width, 6),
),
}
text := svgWriter(b, 0)
fmt.Println(text)
}
func combine[T any](d ...[]T) []T {
var data []T
for _, svgs := range d {
data = append(data, svgs...)
}
return data
}
// Shorthand rounding.
func r(x float64) float64 { return math.Round(x*100) / 100 }
// Potential Abstraction for later.
func hasChildren(svg SVG) bool { return len(svg.Children()) > 0 }
func svgStart(svg SVG, indent int) string {
s := strings.Repeat("\t", indent) + "<" + svg.Type() + " " + svgFields(svg)
if !hasChildren(svg) {
s += "/"
}
s += ">\n"
return s
}
func svgEnd(svg SVG, indent int) string {
if hasChildren(svg) {
return strings.Repeat("\t", indent) + "</" + svg.Type() + ">\n"
}
return ""
}
// svgWriter used for recursion
func svgWriter(svg SVG, indent int) string {
s := svgStart(svg, indent)
for _, child := range svg.Children() {
s += svgWriter(child, indent+1)
}
s += svgEnd(svg, indent)
return s
}
// SVG will allow us to do bullshit god this is dumb.
type SVG interface {
Type() string
Children() []SVG
}
// Body represents a svg body
type Body struct {
Width float64 `svg:"width" unit:"mm"`
Height float64 `svg:"height" unit:"mm"`
Fill string `svg:"fill"`
XMLNS string `svg:"xmlns"`
children []SVG
}
// Children ...
func (b *Body) Children() []SVG { return b.children }
//Type ...
func (b *Body) Type() string { return "svg" }
// Line ...
type Line struct {
X1 float64 `svg:"x1" unit:"mm"`
X2 float64 `svg:"x2" unit:"mm"`
Y1 float64 `svg:"y1" unit:"mm"`
Y2 float64 `svg:"y2" unit:"mm"`
Width float64 `svg:"stroke-width" unit:"mm"`
Stroke string `svg:"stroke"`
}
// Children ...
func (l *Line) Children() []SVG { return nil }
//Type ...
func (l *Line) Type() string { return "line" }
// Circle ...
type Circle struct {
CX float64 `svg:"cx" unit:"mm"`
CY float64 `svg:"cy" unit:"mm"`
Radius float64 `svg:"r" unit:"mm"`
Fill string `svg:"fill"`
Stroke string `svg:"stroke"`
}
// Children ...
func (c *Circle) Children() []SVG { return nil }
//Type ...
func (c *Circle) Type() string { return "circle" }
func svgFields(svg SVG) string {
var fields []string
v := reflect.ValueOf(svg)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
t := v.Type()
for i := 0; i < t.NumField(); i++ {
svgTag := t.Field(i).Tag.Get("svg")
if svgTag == "" {
continue
}
unit := t.Field(i).Tag.Get("unit")
f := v.Field(i)
if f.IsZero() {
continue
}
fields = append(
fields,
fmt.Sprintf(
"%s=\"%v%v\"",
svgTag,
f.Interface(),
unit,
),
)
}
// Lazy as fuck
return strings.Join(fields, " ")
}
func generateLines(thickness float64, size float64, amount int) []SVG {
var svgs []SVG
pad := size / float64(amount)
for i := 0.0; i <= float64(amount); i++ {
svgs = append(
svgs,
&Line{
X1: 2, X2: 13,
Y1: r(pad * i), Y2: r(pad * i),
Width: thickness, Stroke: COLORBLACK,
},
)
}
return svgs
}
/*
D = pos
157.08/6 == 26.18 * (D/100)
*/
var dice = [][][]float64{
{
{50, 50},
},
{
{25, 25},
{75, 75},
},
{
{25, 25},
{50, 50},
{75, 75},
},
{
{25, 25},
{25, 75},
{75, 75},
{75, 25},
},
{
{25, 25},
{25, 75},
{50, 50},
{75, 75},
{75, 25},
},
{
{25, 25},
{25, 50},
{25, 75},
{75, 75},
{75, 50},
{75, 25},
},
}
func generateDice(height float64, width float64, amount int) []SVG {
var svgs []SVG
padHeight := height / float64(amount)
// Algs:
// Even with Height: r((float64(i) * padHeight) + (padHeight * (circle[1] / 100)))
// Scaled for Height
/*
firstPAD = i * padHeight
rPad = padHeight - width
circle[i] * width/100
r((i * padHeight) + ((padHeight-width)/2) + (circle[1] * width/100))
*/
for i, dice := range dice {
for _, circle := range dice {
svgs = append(svgs, &Circle{
CX: circle[0] * (width / 100),
CY: r((float64(i) * padHeight) + ((padHeight - width) / 2) + (circle[1] * width / 100)),
// TODO:
// - Bigger dot for less dots?
Radius: dotSize,
Stroke: COLORBLACK,
Fill: COLORBLACK,
})
}
}
return svgs
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment