vissen-output 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ee97aa25edd367c68a4f113fac72270890711d5859eb61bec40a71470753fb8e
4
+ data.tar.gz: c1069056b86a4f7d62ab4e5d5602bcf5c8131d684e8dc9631955f2582d516e3a
5
+ SHA512:
6
+ metadata.gz: 7475b3b4f78d4fd8f0a656d9dc3e45ade1af5a06e1596df9faa5de8eaa508c3489001b714aaf8f509f9b09d9416ecd99c95ac8682aa17f4cc5ced85003299ad1
7
+ data.tar.gz: 9c552a4b52af3646f6459116e3dda5a297c147886f90c261bb85448b1c978eda53155f68028d186af7b7fa0a77c428e4c9e598ae2ae2ebfb67069e46f2ba54ab
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.rubocop.yml ADDED
@@ -0,0 +1,64 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'vendor/**/*'
4
+ - 'tmp/**/*'
5
+ TargetRubyVersion: 2.5
6
+
7
+ Style/FrozenStringLiteralComment:
8
+ EnforcedStyle: always
9
+
10
+ Layout/EndOfLine:
11
+ EnforcedStyle: lf
12
+
13
+ Layout/ClassStructure:
14
+ Enabled: true
15
+ Categories:
16
+ module_inclusion:
17
+ - include
18
+ - prepend
19
+ - extend
20
+ ExpectedOrder:
21
+ - module_inclusion
22
+ - constants
23
+ - public_class_methods
24
+ - initializer
25
+ - instance_methods
26
+ - protected_methods
27
+ - private_methods
28
+
29
+ Layout/IndentHeredoc:
30
+ EnforcedStyle: squiggly
31
+
32
+ Lint/AmbiguousBlockAssociation:
33
+ Exclude:
34
+ - 'test/**/*.rb'
35
+
36
+ Lint/InterpolationCheck:
37
+ Exclude:
38
+ - 'test/**/*.rb'
39
+
40
+ Metrics/BlockLength:
41
+ Exclude:
42
+ - 'Rakefile'
43
+ - '**/*.rake'
44
+ - 'test/**/*.rb'
45
+
46
+ Metrics/ModuleLength:
47
+ Exclude:
48
+ - 'test/**/*.rb'
49
+
50
+ Metrics/ParameterLists:
51
+ CountKeywordArgs: false
52
+
53
+ Naming/UncommunicativeMethodParamName:
54
+ AllowedNames:
55
+ - x
56
+ - y
57
+ - i
58
+ - p
59
+ - n
60
+ - r
61
+ - g
62
+ - b
63
+ - to
64
+
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.0
5
+ before_install: gem install bundler -v 1.16.1
data/CHANGELOG.md ADDED
@@ -0,0 +1,61 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+ ## [0.6.1] - 2018-04-20
9
+ ### Changed
10
+ - Improved, more descriptive comments.
11
+
12
+ ## [0.6.0] - 2018-04-14
13
+ ### Added
14
+ - Output filter support in PixelBuffer.
15
+ - More descriptive ContextErrors that are raised when contexts do not match.
16
+
17
+ ### Changed
18
+ - Grid context now accepts a with and height instead of an aspect ratio.
19
+
20
+ ## [0.5.1] - 2018-04-14
21
+ ### Added
22
+ - PixelBuffer#finalize!.
23
+ - The convenience method Context::Cloud.scatter that randomly places n points.
24
+
25
+ ### Fixed
26
+ - A bug in the Circle context caused the circle to be centered in (0,0), rather than in the center of the context.
27
+
28
+ ## [0.5.0] - 2018-04-13
29
+ ### Changed
30
+ - Changed the name of the Cloud module to Buffer to distance it from the cloud context.
31
+ - Moved all context to their own submodule.
32
+ - Changed the name of the PixelCloud to PixelBuffer to better indicate what it should be used for.
33
+ - Changed the name of the VixelCloud to VixelBuffer to better indicate what it should be used for.
34
+
35
+ ### Removed
36
+ - The Grid class.
37
+
38
+ ## [0.4.1] - 2018-04-13
39
+ ### Added
40
+ - A Circle context.
41
+
42
+ ### Changed
43
+ - Improved the documentation.
44
+
45
+ ## [0.4.0] - 2018-04-10
46
+ ### Added
47
+ - Output filters.
48
+ - Gamma filter.
49
+ - Quantizer filter.
50
+ - Introduced the more general concept of point clouds.
51
+ - Created the Context as a more general form of the GridContext.
52
+ - Create a new CloudContext that handles arbitrarily positioned Point objects.
53
+
54
+ ### Changed
55
+ - Made the Grid into a special kind of Cloud.
56
+ - Made the VixelGrid into a VixelCloud.
57
+ - Made the PixelGrid into a PixelCloud.
58
+ - The GridContext is now a class instead of a module.
59
+ - The Stack is now longer a GridContext but instead accepts one as its first argument.
60
+ - The argument order of Vixel.new is now reversed, so that is is alphabetical.
61
+ - Renamed Stack -> VixelStack.
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in vissen-output.gemspec
8
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,46 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ vissen-output (0.6.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.0)
10
+ docile (1.3.0)
11
+ json (2.1.0)
12
+ minitest (5.11.3)
13
+ parallel (1.12.1)
14
+ parser (2.5.1.0)
15
+ ast (~> 2.4.0)
16
+ powerpack (0.1.1)
17
+ rainbow (3.0.0)
18
+ rake (10.5.0)
19
+ rubocop (0.55.0)
20
+ parallel (~> 1.10)
21
+ parser (>= 2.5)
22
+ powerpack (~> 0.1)
23
+ rainbow (>= 2.2.2, < 4.0)
24
+ ruby-progressbar (~> 1.7)
25
+ unicode-display_width (~> 1.0, >= 1.0.1)
26
+ ruby-progressbar (1.9.0)
27
+ simplecov (0.16.1)
28
+ docile (~> 1.1)
29
+ json (>= 1.8, < 3)
30
+ simplecov-html (~> 0.10.0)
31
+ simplecov-html (0.10.2)
32
+ unicode-display_width (1.3.0)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ bundler (~> 1.16)
39
+ minitest (~> 5.0)
40
+ rake (~> 10.0)
41
+ rubocop (~> 0.52)
42
+ simplecov (~> 0.16)
43
+ vissen-output!
44
+
45
+ BUNDLED WITH
46
+ 1.16.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Sebastian Lindberg
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Vissen::Output
2
+
3
+ [![Build Status](https://travis-ci.org/midi-visualizer/vissen-output.svg?branch=master)](https://travis-ci.org/midi-visualizer/vissen-output)
4
+ [![Inline docs](http://inch-ci.org/github/midi-visualizer/vissen-output.svg?branch=master)](http://inch-ci.org/github/midi-visualizer/vissen-output)
5
+
6
+ The Vissen Output library implements the objects used by the Vissen Engine to talk to the various sinks.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'vissen-output'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install vissen-output
23
+
24
+ ## Usage
25
+
26
+ TODO: Write usage instructions here
27
+
28
+ ## Development
29
+
30
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
31
+
32
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
33
+
34
+ ## Contributing
35
+
36
+ Bug reports and pull requests are welcome on GitHub at https://github.com/midi-visualizer/vissen-output.
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+ require 'rubocop/rake_task'
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << 'test'
9
+ t.libs << 'lib'
10
+ t.test_files = FileList['test/**/*_test.rb']
11
+ end
12
+
13
+ RuboCop::RakeTask.new(:rubocop) do |t|
14
+ t.options = ['-a']
15
+ end
16
+
17
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'vissen/output'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require 'pry'
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Vissen
6
+ module Output
7
+ # Buffer
8
+ #
9
+ #
10
+ module Buffer
11
+ extend Forwardable
12
+
13
+ # @return [Context] the context of the buffer.
14
+ attr_reader :context
15
+
16
+ # @return [Object] the elements at the buffer points.
17
+ attr_reader :elements
18
+
19
+ def_delegators :@context, :width, :height
20
+ def_delegators :@elements, :each, :each_with_index
21
+
22
+ # The grid is setup with a grid context as well as a class to places
23
+ # instances of in every grid point.
24
+ #
25
+ # @raise [ArgumentError] if both an element class and a block are given.
26
+ #
27
+ # @param context [Context] the context in which the buffer exists.
28
+ # @param elements_klass [Class] the class to use when allocating
29
+ # elements.
30
+ # @param block [Proc] the block to use instead of `elements_klass` when
31
+ # allocating element objects.
32
+ def initialize(context, elements_klass = nil, &block)
33
+ @context = context
34
+ @elements =
35
+ if block_given?
36
+ raise ArgumentError if elements_klass
37
+ context.alloc_points(&block).freeze
38
+ else
39
+ context.alloc_points(elements_klass).freeze
40
+ end
41
+ end
42
+
43
+ # Prevents the context and element array from being changed.
44
+ #
45
+ # @return [self]
46
+ def freeze
47
+ @elements.freeze
48
+ super
49
+ end
50
+
51
+ # Context specific element accessor. Depends on `Context#index_from` to
52
+ # transform `args` into an index.
53
+ #
54
+ # @param args (see Context#index_from).
55
+ # @return [Object] the element at the given index.
56
+ def [](*args)
57
+ @elements[@context.index_from(*args)]
58
+ end
59
+
60
+ # Iterates over each element in the buffer and yields the element along
61
+ # with its x and y coordinates.
62
+ #
63
+ # @return (see Context#each_position).
64
+ def each_with_position
65
+ return to_enum(__callee__) unless block_given?
66
+ @context.each_position { |i, x, y| yield @elements[i], x, y }
67
+ end
68
+
69
+ # Two buffers are considered equal if they share the same context.
70
+ #
71
+ # @param other [#context, Object]
72
+ # @return [true, false] true if the other object share the same context.
73
+ def share_context?(other)
74
+ @context == other.context
75
+ rescue NoMethodError
76
+ false
77
+ end
78
+
79
+ alias === share_context?
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Vissen
4
+ module Output
5
+ # Basic value object representing a color in the RGB color space.
6
+ #
7
+ # == Usage
8
+ # The following example creates two colors, mixes them, and converts the
9
+ # result to an array of color component.
10
+ #
11
+ # color_a = Color.new 0.3, 0.6, 0.2
12
+ # color_b = Color.new 0.1, 0.2, 0.5
13
+ #
14
+ # color_a.mix_with(color_b, 0.5).to_a => [0.2, 0.3, 0.35]
15
+ #
16
+ class Color
17
+ # Accessors for the red, green and blue color components.
18
+ attr_accessor :r, :g, :b
19
+
20
+ # @param r [Float] the red color value in the range (0..1).
21
+ # @param g [Float] the green color value in the range (0..1).
22
+ # @param b [Float] the blue color value in the range (0..1).
23
+ def initialize(r = 0.0, g = 0.0, b = 0.0)
24
+ @r = r
25
+ @g = g
26
+ @b = b
27
+ end
28
+
29
+ # Color equality based on component values.
30
+ #
31
+ # TODO: Add some small delta around what is considered the same color?
32
+ # Perhaps scale to 255 and floor before comparing?
33
+ #
34
+ # @param other [Object] the object to check equality against.
35
+ # @return [true, false] true when two colors are exactly the same.
36
+ def ==(other)
37
+ r == other.r && g == other.g && b == other.b
38
+ rescue NoMethodError
39
+ false
40
+ end
41
+
42
+ # Creates a new array from the color.
43
+ #
44
+ # @return [Array<Float>] a new array containing the red, green and blue
45
+ # color values.
46
+ def to_a
47
+ [r, g, b]
48
+ end
49
+
50
+ # rubocop:disable Metrics/AbcSize
51
+
52
+ # Moves this color toword the other based on the given ratio.
53
+ #
54
+ # ratio = 0 -> 100 % of this color
55
+ # ratio = 1 -> 100 % of the other color
56
+ #
57
+ # @param other [Color] the color to mix with
58
+ # @param ratio [Float] the amount (0..1) of the other color to mix in.
59
+ # @return [self]
60
+ def mix_with!(other, ratio)
61
+ anti_ratio = (1 - ratio)
62
+
63
+ self.r = r * anti_ratio + other.r * ratio
64
+ self.g = g * anti_ratio + other.g * ratio
65
+ self.b = b * anti_ratio + other.b * ratio
66
+
67
+ self
68
+ end
69
+ # rubocop:enable Metrics/AbcSize
70
+
71
+ # Returns a new color that is a mix between this and the other color,
72
+ # based on the ratio. See `#mix_with!` for more details.
73
+ #
74
+ # @param (see #mix_with!)
75
+ # @return [Color] the result of the mix.
76
+ def mix_with(other, ratio)
77
+ dup.mix_with! other, ratio
78
+ end
79
+
80
+ # Returns a string formatted in the tradiotioal hex representation of a
81
+ # color: #04A4BF.
82
+ #
83
+ # @return [String] the object string representation.
84
+ def inspect
85
+ format('#%02X%02X%02X', *to_a.map! { |v| (v * 255).round })
86
+ end
87
+
88
+ class << self
89
+ # Cast a given object to a color.
90
+ #
91
+ # @param obj [Color, Array<Numeric>, Integer, #to_a] the object to
92
+ # coerce.
93
+ # @return [Color] a new color object.
94
+ def from(obj)
95
+ case obj
96
+ when self then obj
97
+ when Array then new(*obj)
98
+ when Integer then from_integer obj
99
+ else
100
+ new(*obj.to_a)
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ def from_integer(int)
107
+ b = (int & 0xFF) / 255.0
108
+ int >>= 8
109
+ g = (int & 0xFF) / 255.0
110
+ int >>= 8
111
+ r = (int & 0xFF) / 255.0
112
+
113
+ new r, g, b
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Vissen
4
+ module Output
5
+ module Context
6
+ # Output context with the points placed counter clockwise on a circle. By
7
+ # specifying an offset it is possible to adjust the position of the end
8
+ # points of the element array.
9
+ class Circle < Cloud
10
+ # @param point_count [Integer] the number of points.
11
+ # @param offset [Numeric] the angle offset, in radians, of the first
12
+ # point.
13
+ # @param width [Numeric] (see Context)
14
+ # @param height [Numeric] (see Context)
15
+ # @param radius [Numeric] the radius of the context.
16
+ # @param args (see CloudContext).
17
+ def initialize(point_count,
18
+ offset: 0,
19
+ width: 1.0,
20
+ height: 1.0,
21
+ radius: [width, height].min / 2.0,
22
+ **args)
23
+
24
+ circle = self.class.position_generator(point_count, radius, offset)
25
+ center = [width.to_f / 2, height.to_f / 2]
26
+ points = self.class.place_points circle, center
27
+
28
+ super(points, width: width, height: height, **args)
29
+ end
30
+
31
+ class << self
32
+ # Creates a generator (`Enumerator`) for x and y coordinates
33
+ # equidistantly placed along a circle centered around (0, 0).
34
+ #
35
+ # @param point_count [Integer] the number of points along the circle.
36
+ # @param radius [Numeric] the radius of the circle.
37
+ # @param offset [Numeric] the angular offset of the first point. An
38
+ # offset of pi/2 would place the first point at the twelve o'clock
39
+ # position.
40
+ # @return [Enumerator] an enumerator that yields `point_count` x and y
41
+ # coordinates along a circle.
42
+ def position_generator(point_count, radius, offset = 0)
43
+ angle_factor = 2.0 * Math::PI / point_count
44
+
45
+ Enumerator.new(point_count) do |y|
46
+ point_count.times do |index|
47
+ angle = index * angle_factor + offset
48
+ y << [radius * Math.cos(angle), radius * Math.sin(angle)]
49
+ end
50
+ end
51
+ end
52
+
53
+ # Uses a position generator to allocate an array of `Point` objects
54
+ # placed arount a circle centered around the given coordinates.
55
+ #
56
+ # @param generator [Enumerator] the position generator
57
+ # (see .position_generator).
58
+ # @param center [Array<Numeric>] the x and y coordinates of the
59
+ # circle center.
60
+ # @return [Array<Point>] an array of `Point` objects placed around a
61
+ # circle.
62
+ def place_points(generator, center)
63
+ x0, y0 = center
64
+ generator.map { |x, y| Point.new x0 + x, y0 + y }
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end