vector_salad 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +89 -0
- data/Rakefile +2 -0
- data/bin/vector_salad +72 -0
- data/examples/birthday.png +0 -0
- data/examples/birthday.rb +45 -0
- data/examples/birthday.svg +630 -0
- data/examples/boolean_operations.png +0 -0
- data/examples/boolean_operations.rb +23 -0
- data/examples/boolean_operations.svg +151 -0
- data/examples/bp_logo.png +0 -0
- data/examples/bp_logo.rb +18 -0
- data/examples/bp_logo.svg +25 -0
- data/examples/bunny_card.png +0 -0
- data/examples/bunny_card.rb +219 -0
- data/examples/bunny_card.svg +134 -0
- data/examples/chill.png +0 -0
- data/examples/chill.rb +16 -0
- data/examples/chill.svg +86 -0
- data/examples/circle_line_segments.png +0 -0
- data/examples/circle_line_segments.rb +11 -0
- data/examples/circle_line_segments.svg +28 -0
- data/examples/circles.png +0 -0
- data/examples/circles.rb +14 -0
- data/examples/circles.svg +11 -0
- data/examples/clip_operations.png +0 -0
- data/examples/clip_operations.rb +14 -0
- data/examples/clip_operations.svg +8 -0
- data/examples/cog_menu.png +0 -0
- data/examples/cog_menu.rb +32 -0
- data/examples/cog_menu.svg +37 -0
- data/examples/cubic_bezier_handles.png +0 -0
- data/examples/cubic_bezier_handles.rb +21 -0
- data/examples/cubic_bezier_handles.svg +14 -0
- data/examples/cubic_circle.png +0 -0
- data/examples/cubic_circle.rb +26 -0
- data/examples/cubic_circle.svg +29 -0
- data/examples/face.png +0 -0
- data/examples/face.rb +4 -0
- data/examples/face.svg +10 -0
- data/examples/flower.png +0 -0
- data/examples/flower.rb +23 -0
- data/examples/flower.svg +207 -0
- data/examples/fox.png +0 -0
- data/examples/fox.rb +110 -0
- data/examples/fox.svg +31 -0
- data/examples/fresh_vector_salad_gui.png +0 -0
- data/examples/galaxies.png +0 -0
- data/examples/galaxies.rb +60 -0
- data/examples/galaxies.svg +5806 -0
- data/examples/gold_stars.png +0 -0
- data/examples/gold_stars.rb +9 -0
- data/examples/gold_stars.svg +12 -0
- data/examples/paths.png +0 -0
- data/examples/paths.rb +87 -0
- data/examples/paths.svg +13 -0
- data/examples/pepsi_logo.png +0 -0
- data/examples/pepsi_logo.rb +21 -0
- data/examples/pepsi_logo.svg +10 -0
- data/examples/polygons.png +0 -0
- data/examples/polygons.rb +9 -0
- data/examples/polygons.svg +13 -0
- data/examples/quadratic_bezier_handle.png +0 -0
- data/examples/quadratic_bezier_handle.rb +18 -0
- data/examples/quadratic_bezier_handle.svg +13 -0
- data/examples/rects.png +0 -0
- data/examples/rects.rb +10 -0
- data/examples/rects.svg +11 -0
- data/examples/simple_path.png +0 -0
- data/examples/simple_path.rb +29 -0
- data/examples/simple_path.svg +8 -0
- data/examples/space.png +0 -0
- data/examples/space.rb +171 -0
- data/examples/space.svg +46453 -0
- data/examples/spiro_nodes.png +0 -0
- data/examples/spiro_nodes.rb +20 -0
- data/examples/spiro_nodes.svg +13 -0
- data/examples/squares.png +0 -0
- data/examples/squares.rb +14 -0
- data/examples/squares.svg +11 -0
- data/examples/stars.png +0 -0
- data/examples/stars.rb +3 -0
- data/examples/stars.svg +30006 -0
- data/examples/transforms.png +0 -0
- data/examples/transforms.rb +58 -0
- data/examples/transforms.svg +121 -0
- data/examples/triangles.png +0 -0
- data/examples/triangles.rb +8 -0
- data/examples/triangles.svg +9 -0
- data/lib/contracts_contracts.rb +32 -0
- data/lib/vector_salad.rb +5 -0
- data/lib/vector_salad/canvas.rb +27 -0
- data/lib/vector_salad/dsl.rb +41 -0
- data/lib/vector_salad/export_with_magic.rb +29 -0
- data/lib/vector_salad/exporters/base_exporter.rb +92 -0
- data/lib/vector_salad/exporters/svg_exporter.rb +174 -0
- data/lib/vector_salad/interpolate.rb +57 -0
- data/lib/vector_salad/magic.rb +17 -0
- data/lib/vector_salad/mixins/at.rb +28 -0
- data/lib/vector_salad/shape_proxy.rb +14 -0
- data/lib/vector_salad/standard_shapes/basic_shape.rb +29 -0
- data/lib/vector_salad/standard_shapes/circle.rb +64 -0
- data/lib/vector_salad/standard_shapes/clip.rb +51 -0
- data/lib/vector_salad/standard_shapes/custom.rb +28 -0
- data/lib/vector_salad/standard_shapes/difference.rb +28 -0
- data/lib/vector_salad/standard_shapes/exclusion.rb +28 -0
- data/lib/vector_salad/standard_shapes/flip.rb +24 -0
- data/lib/vector_salad/standard_shapes/hexagon.rb +15 -0
- data/lib/vector_salad/standard_shapes/intersection.rb +28 -0
- data/lib/vector_salad/standard_shapes/iso_tri.rb +39 -0
- data/lib/vector_salad/standard_shapes/jitter.rb +33 -0
- data/lib/vector_salad/standard_shapes/move.rb +24 -0
- data/lib/vector_salad/standard_shapes/multi_path.rb +82 -0
- data/lib/vector_salad/standard_shapes/n.rb +112 -0
- data/lib/vector_salad/standard_shapes/oval.rb +51 -0
- data/lib/vector_salad/standard_shapes/path.rb +249 -0
- data/lib/vector_salad/standard_shapes/pentagon.rb +15 -0
- data/lib/vector_salad/standard_shapes/polygon.rb +37 -0
- data/lib/vector_salad/standard_shapes/rect.rb +34 -0
- data/lib/vector_salad/standard_shapes/rotate.rb +24 -0
- data/lib/vector_salad/standard_shapes/scale.rb +34 -0
- data/lib/vector_salad/standard_shapes/square.rb +34 -0
- data/lib/vector_salad/standard_shapes/transform.rb +20 -0
- data/lib/vector_salad/standard_shapes/triangle.rb +15 -0
- data/lib/vector_salad/standard_shapes/union.rb +28 -0
- data/lib/vector_salad/version.rb +3 -0
- data/vector_salad.gemspec +34 -0
- metadata +262 -0
Binary file
|
@@ -0,0 +1,58 @@
|
|
1
|
+
@width = 320.0
|
2
|
+
# Background
|
3
|
+
rect(@width, @width * 2, fill: 'tan')
|
4
|
+
|
5
|
+
# Draw a row of repeating shapes at a y position cycling through colors
|
6
|
+
def row(shape, y)
|
7
|
+
n, col = 16, %w(firebrick darkorange white saddlebrown black).shuffle
|
8
|
+
(1..n - 1).each do |x|
|
9
|
+
col.rotate! # cycle through the colors
|
10
|
+
(options = shape.options.clone)[:fill] = col[0]
|
11
|
+
(s = shape.clone).options = options
|
12
|
+
canvas << s.move(@width / n * x, y)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
row(Circle.new(5), 15)
|
17
|
+
|
18
|
+
(1..7).each do |x| # Triangle snake
|
19
|
+
if x.even?
|
20
|
+
iso_tri(30, at: [x * 40, -60], fill: 'darkorange').flip_x
|
21
|
+
else
|
22
|
+
iso_tri(30, at: [x * 40, 30], fill: 'firebrick')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
row(Pentagon.new(6), 80)
|
27
|
+
|
28
|
+
# Toothy face
|
29
|
+
rect(320, 160, at: [0, 100], fill: 'saddlebrown')
|
30
|
+
|
31
|
+
flip(:x) do # flip multiple shapes at once
|
32
|
+
6.times { |x| iso_tri(30, 100, at: [x * 30 + 85, -200], fill: 'white') }
|
33
|
+
iso_tri(50, 20, at: [35, -145], fill: 'black')
|
34
|
+
iso_tri(50, 20, at: [285, -145], fill: 'black')
|
35
|
+
circle(7, at: [35, -160], fill: 'firebrick')
|
36
|
+
circle(7, at: [285, -160], fill: 'firebrick')
|
37
|
+
end
|
38
|
+
7.times { |x| iso_tri(30, 100, at: [x * 30 + 70, @width / 2], fill: 'white') }
|
39
|
+
|
40
|
+
row(Pentagon.new(6), 280)
|
41
|
+
|
42
|
+
# Triangle rosette
|
43
|
+
n, col1, col2 = 14, %w(firebrick white), %w(darkorange black)
|
44
|
+
n.times do |t|
|
45
|
+
col1.rotate!
|
46
|
+
col2.rotate!
|
47
|
+
move(@width / 2, 450) do
|
48
|
+
iso_tri(20, at: [0, -120], fill: col2[0]).rotate(360.0 / n * t)
|
49
|
+
iso_tri(25, at: [0, 120], fill: col1[0]).rotate(360.0 / n * t + 180.0 / n)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# "Diamond"
|
53
|
+
intersection(fill: 'firebrick') do
|
54
|
+
triangle(80, at: [0, 0]).flip_x
|
55
|
+
pentagon(60, at: [0, 0])
|
56
|
+
end.move(@width/2,450)
|
57
|
+
|
58
|
+
row(Circle.new(5), 625)
|
@@ -0,0 +1,121 @@
|
|
1
|
+
<svg version="1.1"
|
2
|
+
xmlns="http://www.w3.org/2000/svg"
|
3
|
+
width="320.0"
|
4
|
+
height="640.0">
|
5
|
+
|
6
|
+
<rect x="0" y="0" width="320.0" height="640.0" fill="tan"/>
|
7
|
+
<circle cx="20.0" cy="15" r="5" fill="black"/>
|
8
|
+
<circle cx="40.0" cy="15" r="5" fill="saddlebrown"/>
|
9
|
+
<circle cx="60.0" cy="15" r="5" fill="firebrick"/>
|
10
|
+
<circle cx="80.0" cy="15" r="5" fill="darkorange"/>
|
11
|
+
<circle cx="100.0" cy="15" r="5" fill="white"/>
|
12
|
+
<circle cx="120.0" cy="15" r="5" fill="black"/>
|
13
|
+
<circle cx="140.0" cy="15" r="5" fill="saddlebrown"/>
|
14
|
+
<circle cx="160.0" cy="15" r="5" fill="firebrick"/>
|
15
|
+
<circle cx="180.0" cy="15" r="5" fill="darkorange"/>
|
16
|
+
<circle cx="200.0" cy="15" r="5" fill="white"/>
|
17
|
+
<circle cx="220.0" cy="15" r="5" fill="black"/>
|
18
|
+
<circle cx="240.0" cy="15" r="5" fill="saddlebrown"/>
|
19
|
+
<circle cx="260.0" cy="15" r="5" fill="firebrick"/>
|
20
|
+
<circle cx="280.0" cy="15" r="5" fill="darkorange"/>
|
21
|
+
<circle cx="300.0" cy="15" r="5" fill="white"/>
|
22
|
+
<path d="M 40 30 L 10 60 L 70 60 Z" fill="firebrick"/>
|
23
|
+
<path d="M 80 60 L 50 30 L 110 30 Z" fill="darkorange"/>
|
24
|
+
<path d="M 120 30 L 90 60 L 150 60 Z" fill="firebrick"/>
|
25
|
+
<path d="M 160 60 L 130 30 L 190 30 Z" fill="darkorange"/>
|
26
|
+
<path d="M 200 30 L 170 60 L 230 60 Z" fill="firebrick"/>
|
27
|
+
<path d="M 240 60 L 210 30 L 270 30 Z" fill="darkorange"/>
|
28
|
+
<path d="M 280 30 L 250 60 L 310 60 Z" fill="firebrick"/>
|
29
|
+
<path d="M 16.47328848624516 84.85410196624969 L 14.293660902229078 78.14589803375031 L 20.0 74.0 L 25.706339097770922 78.14589803375031 L 23.52671151375484 84.85410196624969 Z" fill="darkorange"/>
|
30
|
+
<path d="M 36.47328848624516 84.85410196624969 L 34.29366090222908 78.14589803375031 L 40.0 74.0 L 45.70633909777092 78.14589803375031 L 43.52671151375484 84.85410196624969 Z" fill="firebrick"/>
|
31
|
+
<path d="M 56.47328848624516 84.85410196624969 L 54.29366090222908 78.14589803375031 L 60.0 74.0 L 65.70633909777092 78.14589803375031 L 63.52671151375484 84.85410196624969 Z" fill="saddlebrown"/>
|
32
|
+
<path d="M 76.47328848624517 84.85410196624969 L 74.29366090222908 78.14589803375031 L 80.0 74.0 L 85.70633909777092 78.14589803375031 L 83.52671151375483 84.85410196624969 Z" fill="black"/>
|
33
|
+
<path d="M 96.47328848624517 84.85410196624969 L 94.29366090222908 78.14589803375031 L 100.0 74.0 L 105.70633909777092 78.14589803375031 L 103.52671151375483 84.85410196624969 Z" fill="white"/>
|
34
|
+
<path d="M 116.47328848624517 84.85410196624969 L 114.29366090222908 78.14589803375031 L 120.0 74.0 L 125.70633909777092 78.14589803375031 L 123.52671151375483 84.85410196624969 Z" fill="darkorange"/>
|
35
|
+
<path d="M 136.47328848624517 84.85410196624969 L 134.29366090222908 78.14589803375031 L 140.0 74.0 L 145.70633909777092 78.14589803375031 L 143.52671151375483 84.85410196624969 Z" fill="firebrick"/>
|
36
|
+
<path d="M 156.47328848624517 84.85410196624969 L 154.29366090222908 78.14589803375031 L 160.0 74.0 L 165.70633909777092 78.14589803375031 L 163.52671151375483 84.85410196624969 Z" fill="saddlebrown"/>
|
37
|
+
<path d="M 176.47328848624517 84.85410196624969 L 174.29366090222908 78.14589803375031 L 180.0 74.0 L 185.70633909777092 78.14589803375031 L 183.52671151375483 84.85410196624969 Z" fill="black"/>
|
38
|
+
<path d="M 196.47328848624517 84.85410196624969 L 194.29366090222908 78.14589803375031 L 200.0 74.0 L 205.70633909777092 78.14589803375031 L 203.52671151375483 84.85410196624969 Z" fill="white"/>
|
39
|
+
<path d="M 216.47328848624517 84.85410196624969 L 214.29366090222908 78.14589803375031 L 220.0 74.0 L 225.70633909777092 78.14589803375031 L 223.52671151375483 84.85410196624969 Z" fill="darkorange"/>
|
40
|
+
<path d="M 236.47328848624517 84.85410196624969 L 234.29366090222908 78.14589803375031 L 240.0 74.0 L 245.70633909777092 78.14589803375031 L 243.52671151375483 84.85410196624969 Z" fill="firebrick"/>
|
41
|
+
<path d="M 256.47328848624517 84.85410196624969 L 254.29366090222908 78.14589803375031 L 260.0 74.0 L 265.7063390977709 78.14589803375031 L 263.52671151375483 84.85410196624969 Z" fill="saddlebrown"/>
|
42
|
+
<path d="M 276.47328848624517 84.85410196624969 L 274.2936609022291 78.14589803375031 L 280.0 74.0 L 285.7063390977709 78.14589803375031 L 283.52671151375483 84.85410196624969 Z" fill="black"/>
|
43
|
+
<path d="M 296.47328848624517 84.85410196624969 L 294.2936609022291 78.14589803375031 L 300.0 74.0 L 305.7063390977709 78.14589803375031 L 303.52671151375483 84.85410196624969 Z" fill="white"/>
|
44
|
+
<rect x="0" y="100" width="320" height="160" fill="saddlebrown"/>
|
45
|
+
<path d="M 85 200 L 70 100 L 100 100 Z" fill="white"/>
|
46
|
+
<path d="M 115 200 L 100 100 L 130 100 Z" fill="white"/>
|
47
|
+
<path d="M 145 200 L 130 100 L 160 100 Z" fill="white"/>
|
48
|
+
<path d="M 175 200 L 160 100 L 190 100 Z" fill="white"/>
|
49
|
+
<path d="M 205 200 L 190 100 L 220 100 Z" fill="white"/>
|
50
|
+
<path d="M 235 200 L 220 100 L 250 100 Z" fill="white"/>
|
51
|
+
<path d="M 35 145 L 10 125 L 60 125 Z" fill="black"/>
|
52
|
+
<path d="M 285 145 L 260 125 L 310 125 Z" fill="black"/>
|
53
|
+
<path d="M 42 160 C 42 156.136594828542, 38.863405171458 153, 35 153 C 31.136594828542002 153, 28 156.136594828542, 28 160 C 28 163.863405171458, 31.136594828542002 167, 35 167 C 38.863405171458 167, 42 163.863405171458, 42 160" fill="firebrick"/>
|
54
|
+
<path d="M 292 160 C 292 156.136594828542, 288.863405171458 153, 285 153 C 281.136594828542 153, 278 156.136594828542, 278 160 C 278 163.863405171458, 281.136594828542 167, 285 167 C 288.863405171458 167, 292 163.863405171458, 292 160" fill="firebrick"/>
|
55
|
+
<path d="M 70 160.0 L 55 260.0 L 85 260.0 Z" fill="white"/>
|
56
|
+
<path d="M 100 160.0 L 85 260.0 L 115 260.0 Z" fill="white"/>
|
57
|
+
<path d="M 130 160.0 L 115 260.0 L 145 260.0 Z" fill="white"/>
|
58
|
+
<path d="M 160 160.0 L 145 260.0 L 175 260.0 Z" fill="white"/>
|
59
|
+
<path d="M 190 160.0 L 175 260.0 L 205 260.0 Z" fill="white"/>
|
60
|
+
<path d="M 220 160.0 L 205 260.0 L 235 260.0 Z" fill="white"/>
|
61
|
+
<path d="M 250 160.0 L 235 260.0 L 265 260.0 Z" fill="white"/>
|
62
|
+
<path d="M 16.47328848624516 284.8541019662497 L 14.293660902229078 278.1458980337503 L 20.0 274.0 L 25.706339097770922 278.1458980337503 L 23.52671151375484 284.8541019662497 Z" fill="darkorange"/>
|
63
|
+
<path d="M 36.47328848624516 284.8541019662497 L 34.29366090222908 278.1458980337503 L 40.0 274.0 L 45.70633909777092 278.1458980337503 L 43.52671151375484 284.8541019662497 Z" fill="white"/>
|
64
|
+
<path d="M 56.47328848624516 284.8541019662497 L 54.29366090222908 278.1458980337503 L 60.0 274.0 L 65.70633909777092 278.1458980337503 L 63.52671151375484 284.8541019662497 Z" fill="saddlebrown"/>
|
65
|
+
<path d="M 76.47328848624517 284.8541019662497 L 74.29366090222908 278.1458980337503 L 80.0 274.0 L 85.70633909777092 278.1458980337503 L 83.52671151375483 284.8541019662497 Z" fill="firebrick"/>
|
66
|
+
<path d="M 96.47328848624517 284.8541019662497 L 94.29366090222908 278.1458980337503 L 100.0 274.0 L 105.70633909777092 278.1458980337503 L 103.52671151375483 284.8541019662497 Z" fill="black"/>
|
67
|
+
<path d="M 116.47328848624517 284.8541019662497 L 114.29366090222908 278.1458980337503 L 120.0 274.0 L 125.70633909777092 278.1458980337503 L 123.52671151375483 284.8541019662497 Z" fill="darkorange"/>
|
68
|
+
<path d="M 136.47328848624517 284.8541019662497 L 134.29366090222908 278.1458980337503 L 140.0 274.0 L 145.70633909777092 278.1458980337503 L 143.52671151375483 284.8541019662497 Z" fill="white"/>
|
69
|
+
<path d="M 156.47328848624517 284.8541019662497 L 154.29366090222908 278.1458980337503 L 160.0 274.0 L 165.70633909777092 278.1458980337503 L 163.52671151375483 284.8541019662497 Z" fill="saddlebrown"/>
|
70
|
+
<path d="M 176.47328848624517 284.8541019662497 L 174.29366090222908 278.1458980337503 L 180.0 274.0 L 185.70633909777092 278.1458980337503 L 183.52671151375483 284.8541019662497 Z" fill="firebrick"/>
|
71
|
+
<path d="M 196.47328848624517 284.8541019662497 L 194.29366090222908 278.1458980337503 L 200.0 274.0 L 205.70633909777092 278.1458980337503 L 203.52671151375483 284.8541019662497 Z" fill="black"/>
|
72
|
+
<path d="M 216.47328848624517 284.8541019662497 L 214.29366090222908 278.1458980337503 L 220.0 274.0 L 225.70633909777092 278.1458980337503 L 223.52671151375483 284.8541019662497 Z" fill="darkorange"/>
|
73
|
+
<path d="M 236.47328848624517 284.8541019662497 L 234.29366090222908 278.1458980337503 L 240.0 274.0 L 245.70633909777092 278.1458980337503 L 243.52671151375483 284.8541019662497 Z" fill="white"/>
|
74
|
+
<path d="M 256.47328848624517 284.8541019662497 L 254.29366090222908 278.1458980337503 L 260.0 274.0 L 265.7063390977709 278.1458980337503 L 263.52671151375483 284.8541019662497 Z" fill="saddlebrown"/>
|
75
|
+
<path d="M 276.47328848624517 284.8541019662497 L 274.2936609022291 278.1458980337503 L 280.0 274.0 L 285.7063390977709 278.1458980337503 L 283.52671151375483 284.8541019662497 Z" fill="firebrick"/>
|
76
|
+
<path d="M 296.47328848624517 284.8541019662497 L 294.2936609022291 278.1458980337503 L 300.0 274.0 L 305.7063390977709 278.1458980337503 L 303.52671151375483 284.8541019662497 Z" fill="black"/>
|
77
|
+
<path d="M 160.0 330.0 L 140.0 350.0 L 180.0 350.0 Z" fill="black"/>
|
78
|
+
<path d="M 133.29748792524228 566.9913494618188 L 103.36126677178882 585.8015239174565 L 152.10766238088002 596.9275706152723 Z" fill="white"/>
|
79
|
+
<path d="M 212.06604869410697 341.88373585170973 L 185.36899655370743 351.2254384274069 L 221.40775126980418 368.58078799210926 Z" fill="darkorange"/>
|
80
|
+
<path d="M 85.18122377695198 543.8197778961636 L 50.04819166878289 547.778319911396 L 89.13976579218439 578.9528100043326 Z" fill="firebrick"/>
|
81
|
+
<path d="M 253.81977789616354 375.181223776952 L 225.71335220962828 372.01439016476604 L 250.65294428397766 403.28764946348724 Z" fill="black"/>
|
82
|
+
<path d="M 51.8837358517097 502.066048694107 L 18.51242067621027 490.3889204744855 L 40.20660763208818 535.4373638696064 Z" fill="white"/>
|
83
|
+
<path d="M 276.9913494618188 423.29748792524225 L 253.0423725390561 408.2493483607321 L 261.94320989730863 447.246464848005 Z" fill="darkorange"/>
|
84
|
+
<path d="M 40.0 450.0 L 15.0 425.0 L 15.0 475.0 Z" fill="firebrick"/>
|
85
|
+
<path d="M 276.9913494618188 476.7025120747577 L 261.94320989730863 452.753535151995 L 253.0423725390561 491.7506516392679 Z" fill="black"/>
|
86
|
+
<path d="M 51.8837358517097 397.93395130589306 L 40.20660763208818 364.56263613039357 L 18.51242067621027 409.6110795255146 Z" fill="white"/>
|
87
|
+
<path d="M 253.8197778961636 524.818776223048 L 250.65294428397766 496.71235053651276 L 225.7133522096283 527.985609835234 Z" fill="darkorange"/>
|
88
|
+
<path d="M 85.18122377695201 356.1802221038364 L 89.13976579218443 321.0471899956673 L 50.048191668782934 352.221680088604 Z" fill="firebrick"/>
|
89
|
+
<path d="M 212.066048694107 558.1162641482903 L 221.4077512698042 531.4192120078908 L 185.36899655370743 548.774561572593 Z" fill="black"/>
|
90
|
+
<path d="M 133.29748792524225 333.0086505381812 L 152.10766238088 303.0724293847277 L 103.3612667717888 314.1984760825435 Z" fill="white"/>
|
91
|
+
<path d="M 160.00000000000003 570.0 L 180.0 550.0 L 140.0 550.0 Z" fill="darkorange"/>
|
92
|
+
<path d="M 186.70251207475772 333.0086505381812 L 216.63873322821115 314.19847608254344 L 167.89233761911998 303.07242938472774 Z" fill="firebrick"/>
|
93
|
+
<path d="M 107.93395130589303 558.1162641482903 L 134.6310034462926 548.774561572593 L 98.59224873019582 531.4192120078908 Z" fill="black"/>
|
94
|
+
<path d="M 234.81877622304808 356.18022210383646 L 269.95180833121714 352.22168008860405 L 230.86023420781567 321.0471899956674 Z" fill="white"/>
|
95
|
+
<path d="M 66.18022210383644 524.8187762230481 L 94.2866477903717 527.985609835234 L 69.34705571602235 496.71235053651276 Z" fill="darkorange"/>
|
96
|
+
<path d="M 268.11626414829027 397.933951305893 L 301.4875793237897 409.6110795255145 L 279.7933923679118 364.56263613039357 Z" fill="firebrick"/>
|
97
|
+
<path d="M 43.00865053818117 476.70251207475775 L 66.95762746094394 491.7506516392679 L 58.056790102691366 452.753535151995 Z" fill="black"/>
|
98
|
+
<path d="M 280.0 450.0 L 305.0 475.0 L 305.0 425.0 Z" fill="white"/>
|
99
|
+
<path d="M 43.00865053818117 423.2974879252422 L 58.05679010269135 447.24646484800496 L 66.95762746094395 408.24934836073203 Z" fill="darkorange"/>
|
100
|
+
<path d="M 268.1162641482903 502.06604869410694 L 279.79339236791185 535.4373638696064 L 301.48757932378976 490.3889204744854 Z" fill="firebrick"/>
|
101
|
+
<path d="M 66.18022210383641 375.181223776952 L 69.34705571602234 403.28764946348724 L 94.28664779037169 372.01439016476604 Z" fill="black"/>
|
102
|
+
<path d="M 234.81877622304805 543.8197778961636 L 230.86023420781564 578.9528100043326 L 269.95180833121714 547.778319911396 Z" fill="white"/>
|
103
|
+
<path d="M 107.933951305893 341.88373585170973 L 98.59224873019579 368.58078799210926 L 134.63100344629254 351.2254384274069 Z" fill="darkorange"/>
|
104
|
+
<path d="M 186.70251207475786 566.9913494618188 L 167.89233761912016 596.9275706152723 L 216.63873322821132 585.8015239174565 Z" fill="firebrick"/>
|
105
|
+
<path d=" M 141.83714962005615 498.54101943969727 L 103.05687046051025 431.3716058731079 L 132.47236156463623 410.0 L 187.5276393890381 410.0000009536743 L 216.94313049316406 431.3716058731079 L 178.16285133361816 498.54101943969727 Z" fill="firebrick"/>
|
106
|
+
<circle cx="20.0" cy="625" r="5" fill="saddlebrown"/>
|
107
|
+
<circle cx="40.0" cy="625" r="5" fill="darkorange"/>
|
108
|
+
<circle cx="60.0" cy="625" r="5" fill="black"/>
|
109
|
+
<circle cx="80.0" cy="625" r="5" fill="white"/>
|
110
|
+
<circle cx="100.0" cy="625" r="5" fill="firebrick"/>
|
111
|
+
<circle cx="120.0" cy="625" r="5" fill="saddlebrown"/>
|
112
|
+
<circle cx="140.0" cy="625" r="5" fill="darkorange"/>
|
113
|
+
<circle cx="160.0" cy="625" r="5" fill="black"/>
|
114
|
+
<circle cx="180.0" cy="625" r="5" fill="white"/>
|
115
|
+
<circle cx="200.0" cy="625" r="5" fill="firebrick"/>
|
116
|
+
<circle cx="220.0" cy="625" r="5" fill="saddlebrown"/>
|
117
|
+
<circle cx="240.0" cy="625" r="5" fill="darkorange"/>
|
118
|
+
<circle cx="260.0" cy="625" r="5" fill="black"/>
|
119
|
+
<circle cx="280.0" cy="625" r="5" fill="white"/>
|
120
|
+
<circle cx="300.0" cy="625" r="5" fill="firebrick"/>
|
121
|
+
</svg>
|
Binary file
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<svg version="1.1"
|
2
|
+
xmlns="http://www.w3.org/2000/svg"
|
3
|
+
width="150"
|
4
|
+
height="400">
|
5
|
+
|
6
|
+
<path d="M 100 50 L 50 100 L 150 100 Z"/>
|
7
|
+
<path d="M 56.698729810778076 245.00000000000003 L 99.99999999999999 170.0 L 143.30127018922195 244.99999999999997 Z" fill="#666"/>
|
8
|
+
<path d="M 100 300 L 75 400 L 125 400 Z" fill="lightgrey"/>
|
9
|
+
</svg>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# @private
|
2
|
+
module Contracts
|
3
|
+
class Coords
|
4
|
+
def self.valid? val
|
5
|
+
Maybe[[Num, Num]].valid? val
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.to_s
|
9
|
+
"[Num, Num] an x,y coordinate array"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Coord
|
14
|
+
def self.valid? val
|
15
|
+
Num.valid? val
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.to_s
|
19
|
+
"Num; a coordinate"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class PolySides
|
24
|
+
def self.valid? val
|
25
|
+
Num.valid?(val) && val >= 3
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.to_s
|
29
|
+
"Num; sides of the polygon, minimum of 3"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/vector_salad.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module VectorSalad
|
2
|
+
class Canvas
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@canvas = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def <<(shape)
|
10
|
+
@canvas << shape
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
@canvas.each do |shape|
|
15
|
+
shape = shape.shape if shape.class == VectorSalad::ShapeProxy
|
16
|
+
unless shape.class == VectorSalad::StandardShapes::Custom ||
|
17
|
+
!shape.kind_of?(VectorSalad::StandardShapes::BasicShape)
|
18
|
+
yield(shape)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](i)
|
24
|
+
@canvas[i].class==VectorSalad::ShapeProxy ? @canvas[i].shape : @canvas[i]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'vector_salad/shape_proxy'
|
2
|
+
|
3
|
+
module VectorSalad
|
4
|
+
module DSL
|
5
|
+
def method_missing(name, *args, **options, &block)
|
6
|
+
begin
|
7
|
+
#This automatic require doesn't work properly
|
8
|
+
#require "vector_salad/standard_shapes/#{name}.rb"
|
9
|
+
|
10
|
+
ns = VectorSalad::StandardShapes
|
11
|
+
shape_string = name.to_s.split('_').collect(&:capitalize).join
|
12
|
+
shape_class = ns.const_get(shape_string)
|
13
|
+
|
14
|
+
# No built in is_superclass_of? so implement it ourselves
|
15
|
+
# inlined so it doesn't polute the namespace
|
16
|
+
is_superclass_of_transform = false
|
17
|
+
sub_class = shape_class
|
18
|
+
while sub_class != Object
|
19
|
+
sub_class = sub_class.superclass
|
20
|
+
if sub_class == VectorSalad::StandardShapes::Transform
|
21
|
+
is_superclass_of_transform = true
|
22
|
+
break
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if is_superclass_of_transform
|
27
|
+
shape_instance = shape_class.new(*args, canvas: canvas, **options, &block)
|
28
|
+
else
|
29
|
+
shape_instance = shape_class.new(*args, **options, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
shape_proxy = VectorSalad::ShapeProxy.new(shape_instance)
|
33
|
+
|
34
|
+
canvas << shape_proxy
|
35
|
+
shape_proxy
|
36
|
+
rescue LoadError # no shape available
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'vector_salad/exporters/svg_exporter'
|
2
|
+
require 'vector_salad/canvas'
|
3
|
+
require 'vector_salad/dsl'
|
4
|
+
Dir.glob(File.expand_path('../standard_shapes/*.rb', __FILE__)).each do |file|
|
5
|
+
require file
|
6
|
+
end
|
7
|
+
|
8
|
+
module VectorSalad
|
9
|
+
class ExportWithMagic
|
10
|
+
include VectorSalad::DSL
|
11
|
+
include VectorSalad::StandardShapes
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@options = options
|
15
|
+
@file = options.file
|
16
|
+
end
|
17
|
+
|
18
|
+
def canvas
|
19
|
+
@canvas ||= VectorSalad::Canvas.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def export
|
23
|
+
data = File.read(@file)
|
24
|
+
instance_eval(data, @file)
|
25
|
+
@options.canvas = canvas
|
26
|
+
Exporters::SvgExporter.new(@options).export
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "stringio"
|
2
|
+
|
3
|
+
module VectorSalad
|
4
|
+
module Exporters
|
5
|
+
class BaseExporter
|
6
|
+
attr_reader :canvas
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
@canvas_width = options.width
|
11
|
+
@canvas_height = options.height
|
12
|
+
@canvas = options.canvas
|
13
|
+
@out = StringIO.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def puts(str)
|
17
|
+
@out.puts str + "\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
def gets
|
21
|
+
@out.string
|
22
|
+
end
|
23
|
+
|
24
|
+
def export
|
25
|
+
header
|
26
|
+
body
|
27
|
+
footer
|
28
|
+
|
29
|
+
gets
|
30
|
+
end
|
31
|
+
|
32
|
+
def header; end
|
33
|
+
|
34
|
+
def body
|
35
|
+
format = self.class.name.split('::').last.gsub(/Exporter/, '')
|
36
|
+
.gsub(/(.)([A-Z])/,'\1_\2').downcase
|
37
|
+
convert_method = "to_#{format}".to_sym
|
38
|
+
canvas.each do |shape|
|
39
|
+
begin
|
40
|
+
puts shape.send(convert_method)
|
41
|
+
rescue NameError, NoMethodError
|
42
|
+
puts shape.to_path.send(convert_method)
|
43
|
+
end unless shape.nil?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def footer; end
|
48
|
+
|
49
|
+
def canvas_width
|
50
|
+
get_canvas_sizes unless @canvas_width
|
51
|
+
@canvas_width
|
52
|
+
end
|
53
|
+
|
54
|
+
def canvas_height
|
55
|
+
get_canvas_sizes unless @canvas_height
|
56
|
+
@canvas_height
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
# This method is long and repetetive, for speed. There was a shorter
|
61
|
+
# version that converted every shape to a MultiPath but the performance
|
62
|
+
# was really terrible. This way is a ton faster.
|
63
|
+
def get_canvas_sizes
|
64
|
+
@canvas_width = 0
|
65
|
+
@canvas_height = 0
|
66
|
+
canvas.each do |shape|
|
67
|
+
#if shape.respond_to?(:at) && false
|
68
|
+
#@canvas_width = shape.at[0] if shape.at[0] > @canvas_width
|
69
|
+
#@canvas_height = shape.at[1] if shape.at[1] > @canvas_height
|
70
|
+
#else
|
71
|
+
#shape = shape.to_path
|
72
|
+
shape = shape.to_simple_path
|
73
|
+
|
74
|
+
if shape.class == VectorSalad::StandardShapes::Path
|
75
|
+
shape.nodes.each do |node|
|
76
|
+
@canvas_width = node.at[0] if node.at[0] > @canvas_width
|
77
|
+
@canvas_height = node.at[1] if node.at[1] > @canvas_height
|
78
|
+
end
|
79
|
+
else # MultiPath
|
80
|
+
shape.paths.each do |path|
|
81
|
+
path.nodes.each do |node|
|
82
|
+
@canvas_width = node.at[0] if node.at[0] > @canvas_width
|
83
|
+
@canvas_height = node.at[1] if node.at[1] > @canvas_height
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
#end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require_relative 'base_exporter.rb'
|
2
|
+
Dir.glob(File.expand_path('../../standard_shapes/*.rb', __FILE__)).each do |file|
|
3
|
+
require file
|
4
|
+
end
|
5
|
+
|
6
|
+
module VectorSalad
|
7
|
+
module Exporters
|
8
|
+
class SvgExporter < BaseExporter
|
9
|
+
def header
|
10
|
+
puts <<-END.gsub(/^ {10}/, '')
|
11
|
+
<svg version="1.1"
|
12
|
+
xmlns="http://www.w3.org/2000/svg"
|
13
|
+
width="#{canvas_width}"
|
14
|
+
height="#{canvas_height}">
|
15
|
+
END
|
16
|
+
end
|
17
|
+
|
18
|
+
def footer
|
19
|
+
puts '</svg>'
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.options(options)
|
23
|
+
out = ''
|
24
|
+
options.each do |k, v|
|
25
|
+
out << " #{k.to_s.gsub(/_/, ?-)}=\"#{v.to_s.gsub(/_/, ?-)}\""
|
26
|
+
end
|
27
|
+
out
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
module VectorSalad
|
35
|
+
module StandardShapes
|
36
|
+
class Path
|
37
|
+
def to_svg
|
38
|
+
svg = '<path d="'
|
39
|
+
svg << to_svg_d_attribute
|
40
|
+
svg << '"'
|
41
|
+
svg << VectorSalad::Exporters::SvgExporter.options(@options)
|
42
|
+
svg << '/>'
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_svg_d_attribute
|
46
|
+
nodes = to_bezier_path.nodes
|
47
|
+
svg = ''
|
48
|
+
svg << "M #{nodes[0].x} #{nodes[0].y}"
|
49
|
+
|
50
|
+
nodes[1..-1].each_index do |j|
|
51
|
+
i = j+1
|
52
|
+
|
53
|
+
n = nodes[i]
|
54
|
+
case n.type
|
55
|
+
when :cubic
|
56
|
+
if nodes[i-1].type == :node
|
57
|
+
svg << " C #{n.x} #{n.y}"
|
58
|
+
elsif nodes[i-2].type == :node && nodes[i-1].type == :cubic
|
59
|
+
svg << ", #{n.x} #{n.y}"
|
60
|
+
end
|
61
|
+
when :quadratic
|
62
|
+
svg << " Q #{n.x} #{n.y}"
|
63
|
+
when :node
|
64
|
+
if nodes[i-1].type == :cubic || nodes[i-1].type == :quadratic
|
65
|
+
svg << ", #{n.x} #{n.y}"
|
66
|
+
elsif nodes[i-1].type == :node
|
67
|
+
svg << " L #{n.x} #{n.y}"
|
68
|
+
end
|
69
|
+
else
|
70
|
+
raise "The SVG exporter doesn't support #{n.type} node type."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
svg << ' Z' if @closed
|
75
|
+
svg
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class MultiPath
|
80
|
+
def to_svg
|
81
|
+
svg = '<path d="'
|
82
|
+
paths.each do |path|
|
83
|
+
svg << " #{path.to_svg_d_attribute}"
|
84
|
+
end
|
85
|
+
svg << '"'
|
86
|
+
svg << VectorSalad::Exporters::SvgExporter.options(@options)
|
87
|
+
svg << '/>'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Circle
|
92
|
+
def to_svg
|
93
|
+
svg = "<circle cx=\"#{at[0]}\" cy=\"#{at[1]}\" r=\"#{radius}\""
|
94
|
+
svg << VectorSalad::Exporters::SvgExporter.options(@options)
|
95
|
+
svg << '/>'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Oval
|
100
|
+
def to_svg
|
101
|
+
svg = "<ellipse cx=\"#{at[0]}\" cy=\"#{at[1]}\""
|
102
|
+
svg << " rx=\"#{width}\" ry=\"#{height}\""
|
103
|
+
svg << VectorSalad::Exporters::SvgExporter.options(@options)
|
104
|
+
svg << '/>'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Square
|
109
|
+
def to_svg
|
110
|
+
svg = "<rect x=\"#{at[0]}\" y=\"#{at[1]}\""
|
111
|
+
svg << " width=\"#{size}\" height=\"#{size}\""
|
112
|
+
svg << VectorSalad::Exporters::SvgExporter.options(@options)
|
113
|
+
svg << '/>'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class Rect
|
118
|
+
def to_svg
|
119
|
+
svg = "<rect x=\"#{at[0]}\" y=\"#{at[1]}\""
|
120
|
+
svg << " width=\"#{width}\" height=\"#{height}\""
|
121
|
+
svg << VectorSalad::Exporters::SvgExporter.options(@options)
|
122
|
+
svg << '/>'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
#include VectorSalad::StandardShapes
|
129
|
+
#p = Path.new([0,0], [50,0], [50,50])
|
130
|
+
#puts p.to_svg
|
131
|
+
|
132
|
+
#p1 = Path.new(
|
133
|
+
#N.n(0,100),
|
134
|
+
#N.q(100,0),
|
135
|
+
#N.n(200,100),
|
136
|
+
#N.q(300,200),
|
137
|
+
#N.n(400,100),
|
138
|
+
#N.n(400,200),
|
139
|
+
#N.n(0,200)
|
140
|
+
#)
|
141
|
+
#puts p1.to_svg
|
142
|
+
|
143
|
+
#p2 = Path.new(
|
144
|
+
#N.n(0,100),
|
145
|
+
#N.c(50,150),
|
146
|
+
#N.c(250,150),
|
147
|
+
#N.n(300,100),
|
148
|
+
#N.n(300,50),
|
149
|
+
#N.c(300,0),
|
150
|
+
#N.c(200,50),
|
151
|
+
#N.n(100,50),
|
152
|
+
#N.c(50,0),
|
153
|
+
#N.c(0,0),
|
154
|
+
#N.n(0,50)
|
155
|
+
#)
|
156
|
+
#puts p2.to_svg
|
157
|
+
|
158
|
+
#p3 = Path.new(
|
159
|
+
#N.n(0,200),
|
160
|
+
#N.c(50,000),
|
161
|
+
#N.c(300,100),
|
162
|
+
#N.n(400,150),
|
163
|
+
#N.q(200,500),
|
164
|
+
#N.n(50,300)
|
165
|
+
#)
|
166
|
+
#puts p3.to_svg
|
167
|
+
|
168
|
+
#puts p4.to_svg
|
169
|
+
|
170
|
+
#sq = Square.new(100, at: [50,50])
|
171
|
+
#puts sq.to_path.to_svg
|
172
|
+
|
173
|
+
#ci = Circle.new(100, at: [200,200])
|
174
|
+
#puts ci.to_path.to_svg
|