Let’s make magic circles/runes!
Turn this:
rune do
scale 0.9 do
circle
polygon 7
star 14, 3
star 7, 2
children 7, scale: 1/8r, offset: 1 do |i|
circle
invert do
text (0x2641 + i).chr Encoding::UTF_8
end
end
end
scale 0.15 do
translate x: -2 do circle; moon 0.45 end
circle
translate x: 2 do circle; moon 0.55 end
end
end
Into this:
All through the magic of RUBY!
Dir["./components/*.rb"].sort.each { |file| require file }
r = eval(ARGF.read)
puts r.to_xml
$NON_SCALING_ELEMENTS = %w[circle path polygon line]
class String
def squish
gsub!(/\A[[:space:]]+/, '')
gsub!(/[[:space:]]+\z/, '')
gsub!(/[[:space:]]+/, ' ')
self
end
end
class Node
def initialize(name, children=nil, **attributes)
@name = name
@attributes = attributes
@children = children || []
@attributes['vector-effect'] = 'non-scaling-stroke' if $NON_SCALING_ELEMENTS.include?(@name) or $NON_SCALING_ELEMENTS.include?(@name.to_s)
end
def run(*args, **kwargs, &block)
self.instance_exec(*args, **kwargs, &block)
self
end
def <<(child)
@children.push(child)
self
end
def to_s
parts = []
parts.append @name
parts.append @attributes unless @attributes.empty?
parts.append "[" + @children.map{ |n| n.to_s }.join(", ") + "]" unless @children.empty?
return "Node<#{parts.join(" ")}>"
end
def to_xml(depth: 0)
xml = %(#{' ' * depth}<#{@name})
xml += " " + @attributes.map { |k, v| "#{k}=\"#{v}\"" }.join(" ") unless @attributes.empty?
if @children.empty?
xml += " />\n"
else
xml += ">\n"
@children.map do |child|
if child.is_a? Node
xml += child.to_xml(depth: depth + 1)
else
xml += "#{' ' * (depth + 1)}#{child.to_s}\n"
end
end
xml += "#{' ' * depth}</#{@name}>\n"
end
return xml
end
end
def rune(&block)
Node.new(:svg, xmlns: "http://www.w3.org/2000/svg", viewBox: "-100 -100 200 200") <<
Node.new(:g, transform: "rotate(180)", stroke: "black", fill: "white").run(&block)
end
Node.class_eval do
def children(ls, scale: 1, offset: 0, &block)
ls = *(0..ls-1) if ls.is_a? Integer
group = Node.new(:g)
ls.each_with_index do |el, i|
group << Node.new(:g, transform: %(
rotate(#{i*360.0/ls.length})
translate(0 #{100*offset.to_f})
scale(#{scale.to_f})
).squish).run(el, &block)
end
@children.push(group)
self
end
end
Node.class_eval do
def circle
@children.push(Node.new(:circle, cx: 0, cy: 0, r: 100))
self
end
def dividedCircle(divisions, width: 1)
circle
style width: 1 do
children divisions do line min: 1-width end
end
scale 1-width do circle end
end
def arc(min: 0, max: 360, width: 0.1)
x1, y1, x2, y2, flag = calculateArc(2 * Math::PI * min / 360, 2 * Math::PI * max / 360)
@children.push(
Node.new(:g, fill: "none") <<
Node.new(:path, d: %(
M #{x1} #{y1}
A 100 100, 0, #{flag}, 0, #{x2} #{y2}
).squish)
)
self
end
def moon(phase)
x1, y1, x2, y2, f1 = calculateArc(Math::PI * phase, -Math::PI * phase)
flip = phase < 0.5 ? 1 : 0
rotate 90 do
@children.push(
Node.new(:path, d: %(
M #{x1} #{y1}
A 100 100, 0, #{flip}, #{1-flip}, #{x2} #{y2}
A 100 100, 0, #{1-flip}, #{flip}, #{x1} #{y1}
).squish)
)
end
self
end
private
def calculateArc(min, max)
# https://stackoverflow.com/questions/5736398/how-to-calculate-the-svg-path-for-an-arc-of-a-circle
# Rotate so 0 is the top
min += Math::PI / 2
max += Math::PI / 2
startX = (100 * Math.cos(max)).round(4)
startY = (100 * Math.sin(max)).round(4)
endX = (100 * Math.cos(min)).round(4)
endY = (100 * Math.sin(min)).round(4)
largeArcFlag = max - min <= 180 ? "0" : "1"
return startX, startY, endX, endY, largeArcFlag
end
end
Node.class_eval do
def double(width, &block)
run(&block)
scale(1-width) { run(&block) }
self
end
def invert(&block)
rotate 180, &block
end
def transform(**kwargs, &block)
ls = []
ls.append("rotate(#{kwargs[:rotate].to_f})") if kwargs.include? :rotate
ls.append("scale(#{kwargs[:scale].to_f})") if kwargs.include? :scale
ls.append("translate(#{100*(kwargs[:translateX] || 0).to_f},#{100*(kwargs[:translateY] || 0).to_f})") if kwargs.include?(:translateX) || kwargs.include?(:translateY)
ls.append("skewX(#{kwargs[:skewX].to_f})") if kwargs.include? :skewX
ls.append("skewY(#{kwargs[:skewY].to_f})") if kwargs.include? :skewY
@children.push(Node.new(:g, transform: ls.join(" ")).run(&block))
self
end
def rotate(degrees, &block)
transform(rotate: degrees, &block)
end
def scale(scale, &block)
transform(scale: scale, &block)
end
def translate(x: nil, y: nil, &block)
transform(translateX: x, translateY: y, &block)
end
def skew(x: nil, y: nil, &block)
transform(skewX: x, skewY: y, &block)
end
def style(width: nil, color: nil, fill: nil, &block)
as = {}
as[:"stroke-width"] = width if width
as[:stroke] = color if color
as[:fill] = fill if fill
@children.push(Node.new(:g, **as).run(&block))
self
end
end
Node.class_eval do
def line(min: 0, max: 1)
@children.push(Node.new(
:line,
x1: 0,
y1: 100 * min.to_f,
x2: 0,
y2: 100 * max.to_f
))
self
end
end
Node.class_eval do
def triangle
polygon 3
end
def polygon(points)
star points, 1
end
def star(points, skip)
pstring = points.times.map do |i|
r = 100
theta = Math::PI/2 + 2 * Math::PI / points * (i * skip % points)
x = r * Math.cos(theta)
y = r * Math.sin(theta)
%(#{x},#{y})
end
@children.push(Node.new(:polygon, points: pstring.join(" ")))
self
end
end
Node.class_eval do
def text(text, scale: 1)
@children.push(Node.new(
:text,
stroke: "none",
fill: "black",
"font-size": "#{100*scale.to_f}px",
"text-anchor": "middle",
"dominant-baseline": "central"
) << text)
self
end
def circleText(text, scale: 1)
@children.push(
Node.new(:text,
stroke: "none",
fill: "black",
"font-size": "#{10*scale.to_f}px"
) <<
(Node.new(:textPath, "path": %(
M -100, 0
a 100,100 0 1,0 200,0
a 100,100 0 1,0 -200,0
).squish) << text)
)
self
end
def randomString(set, length)
Array.new(length) { randomSymbol(set) }.join(" ")
end
def randomSymbol(set)
{
:greeklower => [*"α".."ω"],
:greekupper => [*"Α".."Ω"],
:greek => [*"α".."ω", *"Α".."Ω"],
:cyrilliclower => [*"а".."я"],
:cyrillicupper => [*"А".."Я"],
:cyrillic => [*"а".."я", *"А".."Я"],
:mongolian => [*"ᠠ".."ᡯ"],
:hebrew => [*"א".."ת"],
:hiragana => [*"ぁ".."ゖ"],
:egyptian => [*"𓀀".."𓐮"],
:linearb => [*"𐂀".."𐃺"],
:astrological => ["☉", "☽", *"♁".."♇"],
:runic => [*"ᚠ".."ᛪ"],
:chess => [*"♔".."♟"],
:alchemy => [*"🜁".."🝳"],
:arrows => [*"←".."⇿"],
:dingbat => [*"✁".."➿"],
:math => [*"∀".."⋿"],
#:zodiac => [*"♈︎".."♓︎"], # fix emoji issues
}[set].sample
end
end
My goal here was to design a series of functions that each automatically generate parts of an SVG as they’re going, all scaled to a 100.0 unit radius circle (chosen arbitrarily) centered as 0,0. That way, you can do transformations/scaling/etc and it will always work. You can take a large, complicated rune and make it a small subset of another and it will just work(tm).
How?
The core of this code revolves around Ruby’s block syntax. If you aren’t familiar (well, really either way), blocks are a neat little way of passing a bit of code to a function without going so far as to sending around first class functions everywhere (you can do this, but it’s not as elegant). So every time you see do
/end
or {...}
, you can think of that as an inline function call being passed to another function which can do with it what it wants. For example, double
is defined as:
Node.class_eval do
def double(width, &block)
run(&block)
scale(1-width) { run(&block) }
self
end
end
It takes in the width
as a normal parameter and (in this case) explicitly takes a block
. It actually uses another function that I defined (scale
) and calls run
on the &block
twice. Now… that’s a lot of words, most of which is my custom functionality. Let’s take a look at the whole Node
class (in components/_core.rb
), which has a few very powerful functions:
First, how do we create a new Node explicitly:
class Node
def initialize(name, children=nil, **attributes)
@name = name
@attributes = attributes
@children = children || []
@attributes['vector-effect'] = 'non-scaling-stroke' if $NON_SCALING_ELEMENTS.include?(@name) or $NON_SCALING_ELEMENTS.include?(@name.to_s)
end
end
Most of the time, you won’t explicitly add the children
(nodes contained by this node), but you can always set attributes. This is way of assigning arbitrary xml
attributes to the generated svg
. For example:
irb(main):008:0> Node.new(:g, width: 5).to_s
=> "Node<g {:width=>5}>"
irb(main):006:0> Node.new(:g, width: 5).to_xml
=> "<g width=\"5\" />\n"
Speaking of which, I have functions that can render Node to either a more explicit string or directly to_xml
:
class Node
def to_s
parts = []
parts.append @name
parts.append @attributes unless @attributes.empty?
parts.append "[" + @children.map{ |n| n.to_s }.join(", ") + "]" unless @children.empty?
return "Node<#{parts.join(" ")}>"
end
def to_xml(depth: 0)
xml = %(#{' ' * depth}<#{@name})
xml += " " + @attributes.map { |k, v| "#{k}=\"#{v}\"" }.join(" ") unless @attributes.empty?
if @children.empty?
xml += " />\n"
else
xml += ">\n"
@children.map do |child|
if child.is_a? Node
xml += child.to_xml(depth: depth + 1)
else
xml += "#{' ' * (depth + 1)}#{child.to_s}\n"
end
end
xml += "#{' ' * depth}</#{@name}>\n"
end
return xml
end
end
to_xml
is a recursive function that always expects children
to be an array of either nodes or text elements. Other things are possible, but will just get to_s
ed, so strange things can happen. Essentially, it’s generating ’nice’ XML for this limited subset of elements. First, the @attributes
map, then (if no children) a closing tag or recursively do the children one level deeper. I like that it properly indents and newlines the output. It makes debugging easier.
Finally, still in Node, we have two more useful functions:
class Node
def run(*args, **kwargs, &block)
self.instance_exec(*args, **kwargs, &block)
self
end
def <<(child)
@children.push(child)
self
end
end
run
we saw before. It looks bizarre, but all it really means is that you’re going to run the given &block
in the context of the current Node
object. This allows you to do things like access the @children
attribute within the block, which is exactly how the basic elements work:
Node.class_eval do
def circle
@children.push(Node.new(:circle, cx: 0, cy: 0, r: 100))
self
end
end
Create a new svg
circle
element as a Node
with a few default attributes and add it to the Node
who is calling this function’s @children
attribute. It’s always centered at the current origin and always 100 units in radius. Anyone using this DSL should never have to worry about explitic radii, instead making everything relative.
Originally, I didn’t use the @children
attribute and instead had the elements implicitly being returned. But that only works for the last element. In a previous version of this work (in Racket), you could return lists of elements and automatically collect them, but that doesn’t work as well in Ruby. But this version works and the end user’s view is the same–even if implementation is a bit more complicated.
The last function (back in Node) is the <<
‘add child’ function. It allows you to more easily nest nodes when writing helper functions. For example, the children
constructor:
Node.class_eval do
def children(ls, scale: 1, offset: 0, &block)
ls = *(0..ls-1) if ls.is_a? Integer
group = Node.new(:g)
ls.each_with_index do |el, i|
group << Node.new(:g, transform: %(
rotate(#{i*360.0/ls.length})
translate(0 #{100*offset.to_f})
scale(#{scale.to_f})
).squish).run(el, &block)
end
@children.push(group)
self
end
end
This is one of the core functions of a ‘magic circle’ generator. You can either give it a number of children or a list of elements and it will evenly space them around a circle, applying a scale
or offset
(from the center) for each. So if you want a series of 1/4 scale circles in a circle themselves:
irb(main):033:2* puts(rune do
irb(main):034:3* children(4, scale: 1/4r, offset: 3/4r) do
irb(main):035:3* circle
irb(main):036:2* end
irb(main):037:0> end.to_xml)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-100 -100 200 200">
<g transform="rotate(180)" stroke="black" fill="white">
<g>
<g transform="rotate(0.0) translate(0 75.0) scale(0.25)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(90.0) translate(0 75.0) scale(0.25)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(180.0) translate(0 75.0) scale(0.25)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(270.0) translate(0 75.0) scale(0.25)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
</svg>
Each one is rotated a different degree automatically, then translated out 3/4 of the default radius (100), and scaled to 1/4. The 1/4r
is a Ruby way of specifying rational constants rather than 1/4
which is integer division and equals 0
. That took a bit to discover. :)
And that’s just about it. I’ve already gone through and done a number of basic functions that can be used to create some pretty awesome examples.
A few more examples:
# https://cdnb.artstation.com/p/assets/covers/images/015/151/525/medium/taylor-richardson-magiccircle.jpg?1547239370
rune do
style width:4 do
dividedCircle 26, width: 1/6r
triangle
invert do
children %w[𓀇 𓁻 𓆣], scale:0.21, offset:5/7r do |s| # ♌ ♊ ♉
double 1/10r do circle end
invert do
text s
end
end
end
children 3, scale:1/3r, offset:11/12r do
double 1/5r do arc min: 115, max: 245, width: 0.2 end
end
scale 0.5 do
circle
translate x: 0 do
dividedCircle 60, width: 2/3r
end
style width:2 do
scale 1/6r do
circle
star 10, 3
scale 1/3r do
invert do triangle end
end
end
end
rotate 200 do
style(fill: "black") { moon 0.45 }
end
end
end
end
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-110 -120 220 220">
<g transform="rotate(180)" stroke="black" fill="white">
<g stroke-width="4">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g stroke-width="1">
<g>
<g transform="rotate(0.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(13.846153846153847) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(27.692307692307693) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(41.53846153846154) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(55.38461538461539) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(69.23076923076923) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(83.07692307692308) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(96.92307692307692) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(110.76923076923077) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(124.61538461538461) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(138.46153846153845) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(152.30769230769232) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(166.15384615384616) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(180.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(193.84615384615384) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(207.69230769230768) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(221.53846153846155) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(235.3846153846154) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(249.23076923076923) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(263.0769230769231) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(276.9230769230769) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(290.7692307692308) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(304.61538461538464) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(318.46153846153845) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(332.3076923076923) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(346.15384615384613) translate(0 0.0) scale(1.0)">
<line x1="0" y1="83.33333333333334" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
<g transform="scale(0.8333333333333334)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<polygon points="6.123233995736766e-15,100.0 -86.60254037844388,-49.99999999999997 86.60254037844383,-50.00000000000004" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<g>
<g transform="rotate(0.0) translate(0 71.42857142857143) scale(0.21)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
𓀇
</text>
</g>
</g>
<g transform="rotate(120.0) translate(0 71.42857142857143) scale(0.21)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
𓁻
</text>
</g>
</g>
<g transform="rotate(240.0) translate(0 71.42857142857143) scale(0.21)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
𓆣
</text>
</g>
</g>
</g>
</g>
<g>
<g transform="rotate(0.0) translate(0 91.66666666666666) scale(0.3333333333333333)">
<g fill="none">
<path d="M 90.6308 -42.2618 A 100 100, 0, 0, 0, -90.6308 -42.2618" vector-effect="non-scaling-stroke" />
</g>
<g transform="scale(0.8)">
<g fill="none">
<path d="M 90.6308 -42.2618 A 100 100, 0, 0, 0, -90.6308 -42.2618" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
<g transform="rotate(120.0) translate(0 91.66666666666666) scale(0.3333333333333333)">
<g fill="none">
<path d="M 90.6308 -42.2618 A 100 100, 0, 0, 0, -90.6308 -42.2618" vector-effect="non-scaling-stroke" />
</g>
<g transform="scale(0.8)">
<g fill="none">
<path d="M 90.6308 -42.2618 A 100 100, 0, 0, 0, -90.6308 -42.2618" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
<g transform="rotate(240.0) translate(0 91.66666666666666) scale(0.3333333333333333)">
<g fill="none">
<path d="M 90.6308 -42.2618 A 100 100, 0, 0, 0, -90.6308 -42.2618" vector-effect="non-scaling-stroke" />
</g>
<g transform="scale(0.8)">
<g fill="none">
<path d="M 90.6308 -42.2618 A 100 100, 0, 0, 0, -90.6308 -42.2618" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
</g>
<g transform="scale(0.5)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="translate(0.0,0.0)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g stroke-width="1">
<g>
<g transform="rotate(0.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(6.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(12.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(18.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(24.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(30.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(36.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(42.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(48.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(54.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(60.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(66.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(72.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(78.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(84.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(90.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(96.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(102.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(108.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(114.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(120.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(126.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(132.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(138.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(144.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(150.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(156.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(162.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(168.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(174.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(180.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(186.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(192.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(198.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(204.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(210.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(216.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(222.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(228.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(234.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(240.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(246.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(252.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(258.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(264.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(270.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(276.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(282.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(288.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(294.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(300.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(306.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(312.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(318.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(324.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(330.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(336.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(342.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(348.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
<g transform="rotate(354.0) translate(0 0.0) scale(1.0)">
<line x1="0" y1="33.33333333333333" x2="0" y2="100.0" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
<g transform="scale(0.3333333333333333)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
</g>
<g stroke-width="2">
<g transform="scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<polygon points="6.123233995736766e-15,100.0 -95.10565162951536,-30.901699437494727 58.77852522924729,-80.90169943749476 58.778525229247336,80.90169943749473 -95.10565162951535,30.901699437494752 -1.8369701987210297e-14,-100.0 95.10565162951536,30.901699437494717 -58.7785252292473,80.90169943749474 -58.77852522924732,-80.90169943749473 95.10565162951535,-30.901699437494766" vector-effect="non-scaling-stroke" />
<g transform="scale(0.3333333333333333)">
<g transform="rotate(180.0)">
<polygon points="6.123233995736766e-15,100.0 -86.60254037844388,-49.99999999999997 86.60254037844383,-50.00000000000004" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
</g>
<g transform="rotate(200.0)">
<g fill="black">
<g transform="rotate(90.0)">
<path d="M 98.7688 15.6434 A 100 100, 0, 1, 0, -98.7688 15.6434 A 100 100, 0, 0, 1, 98.7688 15.6434" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
rune do
scale 0.9 do
circle
polygon 7
star 14, 3
star 7, 2
children 7, scale: 1/8r, offset: 1 do |i|
circle
invert do
text (0x2641 + i).chr Encoding::UTF_8
end
end
end
scale 0.15 do
translate x: -2 do circle; moon 0.45 end
circle
translate x: 2 do circle; moon 0.55 end
end
end
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-110 -120 220 220">
<g transform="rotate(180)" stroke="black" fill="white">
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<polygon points="6.123233995736766e-15,100.0 -78.18314824680299,62.34898018587336 -97.49279121818236,-22.252093395631427 -43.38837391175583,-90.09688679024191 43.38837391175579,-90.09688679024192 97.49279121818235,-22.252093395631466 78.183148246803,62.34898018587334" vector-effect="non-scaling-stroke" />
<polygon points="6.123233995736766e-15,100.0 -97.49279121818236,22.25209339563145 -43.38837391175583,-90.09688679024191 78.18314824680297,-62.34898018587337 78.183148246803,62.34898018587334 -43.38837391175581,90.09688679024191 -97.49279121818236,-22.252093395631427 -1.8369701987210297e-14,-100.0 97.49279121818235,-22.252093395631466 43.38837391175584,90.09688679024191 -78.18314824680299,62.34898018587336 -78.18314824680299,-62.34898018587334 43.38837391175579,-90.09688679024192 97.49279121818236,22.252093395631416" vector-effect="non-scaling-stroke" />
<polygon points="6.123233995736766e-15,100.0 -97.49279121818236,-22.252093395631427 43.38837391175579,-90.09688679024192 78.183148246803,62.34898018587334 -78.18314824680299,62.34898018587336 -43.38837391175583,-90.09688679024191 97.49279121818235,-22.252093395631466" vector-effect="non-scaling-stroke" />
<g>
<g transform="rotate(0.0) translate(0 100.0) scale(0.125)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♁
</text>
</g>
</g>
<g transform="rotate(51.42857142857143) translate(0 100.0) scale(0.125)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♂
</text>
</g>
</g>
<g transform="rotate(102.85714285714286) translate(0 100.0) scale(0.125)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♃
</text>
</g>
</g>
<g transform="rotate(154.28571428571428) translate(0 100.0) scale(0.125)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♄
</text>
</g>
</g>
<g transform="rotate(205.71428571428572) translate(0 100.0) scale(0.125)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♅
</text>
</g>
</g>
<g transform="rotate(257.14285714285717) translate(0 100.0) scale(0.125)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♆
</text>
</g>
</g>
<g transform="rotate(308.57142857142856) translate(0 100.0) scale(0.125)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♇
</text>
</g>
</g>
</g>
</g>
<g transform="scale(0.15)">
<g transform="translate(-200.0,0.0)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(90.0)">
<path d="M 98.7688 15.6434 A 100 100, 0, 1, 0, -98.7688 15.6434 A 100 100, 0, 0, 1, 98.7688 15.6434" vector-effect="non-scaling-stroke" />
</g>
</g>
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="translate(200.0,0.0)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="rotate(90.0)">
<path d="M 98.7688 -15.6434 A 100 100, 0, 0, 1, -98.7688 -15.6434 A 100 100, 0, 1, 0, 98.7688 -15.6434" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
</g>
</svg>
rune do
double(0.05) { circle }
scale(0.95) { [*2..5].each {|i| star 12,i } }
scale 0.99 do
circleText randomString(:runic, 400), scale: 0.4
end
scale 3/4r do
double(0.05) { circle }
scale 0.99 do
circleText randomString(:runic, 400), scale: 0.4
end
style fill: "none" do
triangle
invert { triangle }
end
invert do
children 6, scale: 1/6r, offset:1 do
double(0.1) do
circle
text randomSymbol(:astrological)
end
end
end
end
scale 1/4r do
double(0.1) { circle }
scale 0.9 do
polygon 8
star 8, 3
children 8, scale: 1/6r, offset:1 do
double(0.1) do
circle
text randomSymbol(:greekupper)
end
end
end
scale(0.1) do
skew y: 20 do
arc min: 0, max: 90
arc min: 180, max: 270
end
end
end
end
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-110 -120 220 220">
<g transform="rotate(180)" stroke="black" fill="white">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="scale(0.95)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="scale(0.95)">
<polygon points="6.123233995736766e-15,100.0 -86.60254037844385,50.000000000000036 -86.60254037844388,-49.99999999999997 -1.8369701987210297e-14,-100.0 86.60254037844383,-50.00000000000004 86.6025403784439,49.99999999999993 6.123233995736766e-15,100.0 -86.60254037844385,50.000000000000036 -86.60254037844388,-49.99999999999997 -1.8369701987210297e-14,-100.0 86.60254037844383,-50.00000000000004 86.6025403784439,49.99999999999993" vector-effect="non-scaling-stroke" />
<polygon points="6.123233995736766e-15,100.0 -100.0,1.2246467991473532e-14 -1.8369701987210297e-14,-100.0 100.0,-2.4492935982947064e-14 6.123233995736766e-15,100.0 -100.0,1.2246467991473532e-14 -1.8369701987210297e-14,-100.0 100.0,-2.4492935982947064e-14 6.123233995736766e-15,100.0 -100.0,1.2246467991473532e-14 -1.8369701987210297e-14,-100.0 100.0,-2.4492935982947064e-14" vector-effect="non-scaling-stroke" />
<polygon points="6.123233995736766e-15,100.0 -86.60254037844388,-49.99999999999997 86.60254037844383,-50.00000000000004 6.123233995736766e-15,100.0 -86.60254037844388,-49.99999999999997 86.60254037844383,-50.00000000000004 6.123233995736766e-15,100.0 -86.60254037844388,-49.99999999999997 86.60254037844383,-50.00000000000004 6.123233995736766e-15,100.0 -86.60254037844388,-49.99999999999997 86.60254037844383,-50.00000000000004" vector-effect="non-scaling-stroke" />
<polygon points="6.123233995736766e-15,100.0 -50.00000000000004,-86.60254037844383 86.6025403784439,49.99999999999993 -100.0,1.2246467991473532e-14 86.60254037844383,-50.00000000000004 -49.99999999999998,86.60254037844388 -1.8369701987210297e-14,-100.0 50.00000000000006,86.60254037844383 -86.60254037844388,-49.99999999999997 100.0,-2.4492935982947064e-14 -86.60254037844385,50.000000000000036 49.999999999999936,-86.6025403784439" vector-effect="non-scaling-stroke" />
</g>
<g transform="scale(0.99)">
<text stroke="none" fill="black" font-size="4.0px">
<textPath path="M -100, 0 a 100,100 0 1,0 200,0 a 100,100 0 1,0 -200,0">
ᚿ ᛏ ᛍ ᚸ ᚠ ᛘ ᚵ ᚠ ᛝ ᚵ ᛦ ᚫ ᛦ ᛅ ᚲ ᚲ ᚡ ᚮ ᛝ ᚪ ᛉ ᛓ ᛍ ᚴ ᛁ ᛛ ᛩ ᛛ ᛓ ᛂ ᛋ ᛒ ᛞ ᛏ ᛁ ᛟ ᛌ ᛞ ᚪ ᛒ ᚢ ᚾ ᚷ ᛢ ᚧ ᛖ ᚥ ᛋ ᛡ ᛁ ᛧ ᛙ ᚯ ᛣ ᛅ ᚠ ᛄ ᛥ ᛤ ᛝ ᛔ ᚭ ᛙ ᛡ ᚯ ᚻ ᛜ ᚧ ᚭ ᛀ ᚧ ᚾ ᛅ ᛢ ᚬ ᚳ ᛦ ᛖ ᚲ ᛏ ᛒ ᛚ ᛩ ᛒ ᛂ ᛟ ᛂ ᛥ ᚧ ᛍ ᛑ ᚯ ᚫ ᚴ ᛠ ᛟ ᛣ ᛜ ᚭ ᚻ ᚿ ᛓ ᚿ ᚢ ᚸ ᛂ ᛐ ᛓ ᚬ ᛁ ᛏ ᛖ ᚼ ᛒ ᛁ ᛗ ᛜ ᛝ ᛩ ᛨ ᛤ ᚿ ᛀ ᛚ ᛓ ᛜ ᛓ ᛖ ᛜ ᛟ ᚿ ᛥ ᛨ ᚶ ᚤ ᚾ ᛣ ᛆ ᚻ ᚢ ᛖ ᛜ ᛓ ᛔ ᛍ ᚾ ᛁ ᚮ ᚽ ᛄ ᛄ ᛛ ᛨ ᛩ ᛒ ᛛ ᛅ ᛝ ᚻ ᛡ ᛀ ᛔ ᚽ ᚻ ᛐ ᚻ ᚨ ᛖ ᛤ ᚵ ᚥ ᚩ ᚹ ᚭ ᛆ ᚣ ᛕ ᛣ ᛇ ᚴ ᛙ ᛤ ᚲ ᚩ ᛋ ᛄ ᛠ ᚷ ᚳ ᚽ ᛊ ᛃ ᛊ ᚡ ᛞ ᛘ ᛙ ᛑ ᚼ ᛗ ᚱ ᛥ ᛚ ᛋ ᛐ ᚪ ᚩ ᚮ ᛑ ᛖ ᚨ ᛍ ᚽ ᛝ ᚭ ᛉ ᛠ ᛁ ᛙ ᚲ ᛝ ᛋ ᚾ ᛩ ᚵ ᚡ ᛕ ᚡ ᛐ ᛑ ᛞ ᛐ ᚷ ᛤ ᛈ ᛋ ᛞ ᚾ ᛃ ᛑ ᚫ ᚮ ᚵ ᚶ ᛥ ᛅ ᛧ ᚲ ᚷ ᛣ ᛊ ᚡ ᚨ ᚳ ᚬ ᚡ ᛋ ᚱ ᛀ ᚾ ᚬ ᚦ ᚩ ᛨ ᚱ ᛤ ᛐ ᚴ ᚠ ᛋ ᛌ ᛤ ᚧ ᚤ ᚵ ᚨ ᛄ ᛩ ᛄ ᚶ ᚵ ᚤ ᛓ ᚱ ᛉ ᛀ ᛥ ᛐ ᚾ ᚲ ᛃ ᚥ ᚻ ᚱ ᚪ ᛍ ᛝ ᚬ ᛦ ᛣ ᛌ ᚵ ᛙ ᛍ ᛤ ᚽ ᛎ ᚫ ᚭ ᚾ ᛇ ᚤ ᛓ ᛈ ᚸ ᚣ ᛜ ᛕ ᚤ ᚩ ᛑ ᛑ ᚰ ᛑ ᚿ ᛄ ᛤ ᚹ ᚿ ᚤ ᛥ ᛡ ᚥ ᛓ ᛉ ᚵ ᚻ ᚱ ᛗ ᛟ ᛁ ᛘ ᛔ ᛟ ᛄ ᛊ ᛚ ᛈ ᚥ ᛜ ᚼ ᛪ ᚢ ᛌ ᚥ ᚴ ᚰ ᚬ ᛈ ᛔ ᚷ ᛔ ᛃ ᛄ ᛨ ᚲ ᛗ ᛁ ᛐ ᛃ ᛛ ᛙ ᛖ ᛅ ᚹ ᛑ ᛧ ᚸ ᚧ ᛨ ᚳ ᛙ ᚷ ᛉ ᛨ ᛊ ᚣ ᛔ ᚧ ᚰ ᚮ ᚦ ᛝ ᛋ ᛄ ᛒ ᛆ ᚱ ᛂ ᛏ
</textPath>
</text>
</g>
<g transform="scale(0.75)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="scale(0.95)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="scale(0.99)">
<text stroke="none" fill="black" font-size="4.0px">
<textPath path="M -100, 0 a 100,100 0 1,0 200,0 a 100,100 0 1,0 -200,0">
ᛈ ᛁ ᛋ ᛪ ᛙ ᛘ ᚴ ᛝ ᚪ ᚺ ᛞ ᚿ ᚽ ᚿ ᚤ ᚧ ᚹ ᛍ ᛂ ᛨ ᛛ ᚸ ᚿ ᚪ ᛌ ᛆ ᛐ ᚬ ᛢ ᛧ ᚲ ᛝ ᛤ ᛖ ᛖ ᛧ ᛋ ᚩ ᛈ ᛈ ᚫ ᛊ ᛒ ᚤ ᚪ ᛍ ᛏ ᚾ ᛄ ᚣ ᛄ ᛍ ᚠ ᛔ ᛡ ᚧ ᚢ ᛇ ᚦ ᛔ ᛥ ᛈ ᚰ ᛥ ᛁ ᚡ ᚶ ᚦ ᛧ ᚡ ᛦ ᛋ ᛄ ᛌ ᚿ ᚻ ᛙ ᛒ ᛪ ᚸ ᛦ ᚱ ᛔ ᛉ ᛔ ᛞ ᚵ ᛖ ᛎ ᚺ ᚡ ᛕ ᛤ ᚡ ᚰ ᛆ ᚤ ᚷ ᛜ ᛨ ᛚ ᚥ ᛐ ᚺ ᛨ ᚸ ᚪ ᚮ ᚺ ᛃ ᚾ ᚨ ᛏ ᛥ ᛊ ᛐ ᛂ ᚷ ᛡ ᛅ ᚨ ᛛ ᛧ ᚣ ᚾ ᛄ ᛊ ᛜ ᛛ ᛗ ᚺ ᛌ ᛉ ᛝ ᚲ ᚭ ᚷ ᛉ ᚴ ᚪ ᛗ ᛚ ᛊ ᚽ ᚢ ᛚ ᚯ ᚡ ᚯ ᚱ ᛢ ᚶ ᛋ ᚮ ᛞ ᚦ ᚸ ᚭ ᚫ ᚳ ᛄ ᛗ ᛛ ᚴ ᛔ ᚦ ᚻ ᚺ ᛜ ᛨ ᚣ ᛃ ᛇ ᚵ ᚬ ᚢ ᛌ ᛑ ᛌ ᚭ ᚸ ᚤ ᚻ ᛖ ᛃ ᚿ ᛡ ᛒ ᛚ ᚽ ᚾ ᚭ ᚬ ᛚ ᚭ ᛗ ᚮ ᚨ ᛈ ᚦ ᛣ ᛤ ᛟ ᛇ ᚩ ᛉ ᚿ ᛋ ᛅ ᛄ ᛏ ᛡ ᛖ ᛁ ᚪ ᚩ ᚦ ᚤ ᛝ ᚫ ᛃ ᛖ ᛋ ᚭ ᚥ ᛄ ᚠ ᚲ ᛎ ᛇ ᛘ ᛨ ᚳ ᛃ ᛠ ᛦ ᛊ ᛇ ᛒ ᛅ ᛆ ᚶ ᛍ ᛞ ᛉ ᛪ ᛌ ᛤ ᚧ ᛤ ᛩ ᚢ ᛤ ᚷ ᚳ ᛖ ᛘ ᛄ ᛑ ᚭ ᛍ ᛁ ᛦ ᛉ ᛄ ᛤ ᛇ ᛃ ᛢ ᚴ ᛍ ᛥ ᚿ ᛣ ᛥ ᛝ ᚧ ᛤ ᚾ ᚻ ᛪ ᛒ ᛍ ᚲ ᚿ ᚳ ᛋ ᛋ ᛅ ᛠ ᚸ ᚶ ᚡ ᚳ ᛙ ᛨ ᛝ ᚽ ᛈ ᚪ ᚫ ᚥ ᛦ ᛐ ᛝ ᚳ ᛑ ᚪ ᛩ ᛞ ᛁ ᚾ ᚩ ᛄ ᚧ ᚺ ᛎ ᛧ ᚪ ᚦ ᚱ ᛗ ᚯ ᚾ ᛪ ᛄ ᚫ ᚢ ᛩ ᛊ ᚡ ᛁ ᛦ ᚧ ᛂ ᛃ ᚨ ᚮ ᛥ ᛊ ᛣ ᛡ ᚣ ᚤ ᛈ ᚻ ᚫ ᚡ ᚲ ᚤ ᛌ ᛓ ᚥ ᛡ ᛆ ᛞ ᛞ ᛗ ᚼ ᛁ ᛪ ᚾ ᚣ ᚢ ᛄ ᚺ ᛅ ᛓ ᛢ ᚽ ᛕ ᚥ ᚧ ᚶ ᚳ ᛖ ᚹ ᛧ ᛛ ᛅ ᛟ ᚩ ᛢ ᛠ ᚤ ᛥ ᛀ ᚪ ᛎ ᛙ ᛢ ᛢ ᚪ ᛥ ᛅ ᛪ ᚡ ᚦ ᛤ ᚴ
</textPath>
</text>
</g>
<g fill="none">
<polygon points="6.123233995736766e-15,100.0 -86.60254037844388,-49.99999999999997 86.60254037844383,-50.00000000000004" vector-effect="non-scaling-stroke" />
<g transform="rotate(180.0)">
<polygon points="6.123233995736766e-15,100.0 -86.60254037844388,-49.99999999999997 86.60254037844383,-50.00000000000004" vector-effect="non-scaling-stroke" />
</g>
</g>
<g transform="rotate(180.0)">
<g>
<g transform="rotate(0.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♄
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♃
</text>
</g>
</g>
<g transform="rotate(60.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♂
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♂
</text>
</g>
</g>
<g transform="rotate(120.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♅
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♇
</text>
</g>
</g>
<g transform="rotate(180.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♃
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♁
</text>
</g>
</g>
<g transform="rotate(240.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♃
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♃
</text>
</g>
</g>
<g transform="rotate(300.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♃
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
♅
</text>
</g>
</g>
</g>
</g>
</g>
<g transform="scale(0.25)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
</g>
<g transform="scale(0.9)">
<polygon points="6.123233995736766e-15,100.0 -70.71067811865474,70.71067811865476 -100.0,1.2246467991473532e-14 -70.71067811865477,-70.71067811865474 -1.8369701987210297e-14,-100.0 70.71067811865474,-70.71067811865477 100.0,-2.4492935982947064e-14 70.71067811865477,70.71067811865474" vector-effect="non-scaling-stroke" />
<polygon points="6.123233995736766e-15,100.0 -70.71067811865477,-70.71067811865474 100.0,-2.4492935982947064e-14 -70.71067811865474,70.71067811865476 -1.8369701987210297e-14,-100.0 70.71067811865477,70.71067811865474 -100.0,1.2246467991473532e-14 70.71067811865474,-70.71067811865477" vector-effect="non-scaling-stroke" />
<g>
<g transform="rotate(0.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Ρ
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Θ
</text>
</g>
</g>
<g transform="rotate(45.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Γ
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Σ
</text>
</g>
</g>
<g transform="rotate(90.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Ο
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Β
</text>
</g>
</g>
<g transform="rotate(135.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Ω
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Μ
</text>
</g>
</g>
<g transform="rotate(180.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Κ
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Θ
</text>
</g>
</g>
<g transform="rotate(225.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Ε
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Θ
</text>
</g>
</g>
<g transform="rotate(270.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Δ
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Μ
</text>
</g>
</g>
<g transform="rotate(315.0) translate(0 100.0) scale(0.16666666666666666)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Υ
</text>
<g transform="scale(0.9)">
<circle cx="0" cy="0" r="100" vector-effect="non-scaling-stroke" />
<text stroke="none" fill="black" font-size="100.0px" text-anchor="middle" dominant-baseline="central">
Β
</text>
</g>
</g>
</g>
</g>
<g transform="scale(0.1)">
<g transform="skewX(0.0) skewY(20.0)">
<g fill="none">
<path d="M -100.0 0.0 A 100 100, 0, 0, 0, 0.0 100.0" vector-effect="non-scaling-stroke" />
</g>
<g fill="none">
<path d="M 100.0 0.0 A 100 100, 0, 0, 0, 0.0 -100.0" vector-effect="non-scaling-stroke" />
</g>
</g>
</g>
</g>
</g>
</svg>
It’s wonderful. :D
Next up:
Add rules to make ‘runes’, such as Vegvisir:
Add a system to automatically generate runes that follow certain rules
Onward!