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
<svg width="15mm" height="157.08mm" xmlns="http://www.w3.org/2000/svg">
<line x1="2mm" x2="13mm" stroke-width="2mm" stroke="black"/>
<line x1="2mm" x2="13mm" y1="26.18mm" y2="26.18mm" stroke-width="2mm" stroke="black"/>
<line x1="2mm" x2="13mm" y1="52.36mm" y2="52.36mm" stroke-width="2mm" stroke="black"/>
<line x1="2mm" x2="13mm" y1="78.54mm" y2="78.54mm" stroke-width="2mm" stroke="black"/>
<line x1="2mm" x2="13mm" y1="104.72mm" y2="104.72mm" stroke-width="2mm" stroke="black"/>
<line x1="2mm" x2="13mm" y1="130.9mm" y2="130.9mm" stroke-width="2mm" stroke="black"/>
<line x1="2mm" x2="13mm" y1="157.08mm" y2="157.08mm" stroke-width="2mm" stroke="black"/>
<circle cx="7.5mm" cy="13.09mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="35.52mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="43.02mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="61.7mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="7.5mm" cy="65.45mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="69.2mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="87.88mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="95.38mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="95.38mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="87.88mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="114.06mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="121.56mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="7.5mm" cy="117.81mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="121.56mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="114.06mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="140.24mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="143.99mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="3.75mm" cy="147.74mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="147.74mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="143.99mm" r="1.5mm" fill="black" stroke="black"/>
<circle cx="11.25mm" cy="140.24mm" r="1.5mm" fill="black" stroke="black"/>
</svg>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment