gui_geometry2 3.0.0

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: f5b1ce600043107151ce24dfa9b9ba280b69c45f807d6ede5460157e8d43b01c
4
+ data.tar.gz: 62651f258dabe0f1b435ec77f4342e3400b9ba01eddedd27112c2a9514a04ac9
5
+ SHA512:
6
+ metadata.gz: a9a71af16a2383caf95ce5e77bc8555b0e332aad972c61a92f1fa91d174cf23e3dc89c3036088c93665e08c9d4ce0497bc4b1365f68934fcf7572dab79e9fd5b
7
+ data.tar.gz: a203e70a11d5ca3fc7892a05ca762b5f92f8b8012f0976a6705c0f00afaa8eb82ff03974b460c72053ec15e0cdca6eefd0c616da03645b9da20b84ef1067b4f0
@@ -0,0 +1,22 @@
1
+ # see also https://github.com/whitequark/parser/blob/master/.github/workflows/test.yml
2
+ name: Rake
3
+
4
+ on: [push]
5
+
6
+ jobs:
7
+ test:
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby_version: [head, "4.0", "3.2"]
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby_version }}
20
+ bundler-cache: true # 'bundle install' and cache
21
+ - name: Run the default task
22
+ run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ # ~/.gitignore included
2
+
3
+ **/*.gem
4
+ **/*.lock
5
+ **/*.log
6
+
7
+ .watchr
8
+ coverage
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-4.0.6
data/.watchr ADDED
@@ -0,0 +1 @@
1
+ /home/dk/shared/.watchr-gem
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in gui_geometry.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem "benchmark"
8
+ gem "benchmark-ips"
9
+ gem "cuco"
10
+ gem "ricecream", require: false
11
+ gem "simplecov", require: false
12
+ gem "standard", require: false
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2013 Shane Brinkman-Davis
2
+ Copyright (c) 2026 Dittmar Krall (www.matiq.com)
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # GuiGeo
2
+
3
+ [![Gem Version](https://img.shields.io/gem/v/guigeo2?color=168AFE&logo=rubygems&logoColor=FE1616)](https://rubygems.org/gems/guigeo2)
4
+ [![Downloads](https://img.shields.io/gem/dt/guigeo2?color=168AFE&logo=rubygems&logoColor=FE1616)](https://rubygems.org/gems/guigeo2)
5
+ [![GitHub Build](https://img.shields.io/github/actions/workflow/status/matique/guigeo2/rake.yml?logo=github)](https://github.com/matique/guigeo2/actions/workflows/rake.yml)
6
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-168AFE.svg)](https://github.com/standardrb/standard)
7
+ [![MIT License](https://img.shields.io/badge/license-MIT-168AFE.svg)](http://choosealicense.com/licenses/mit/)
8
+
9
+ There are a few good geometry gems already available for
10
+ Ruby (ruby-geometry and geometry),
11
+ but I need one which is focused on the needs of creating 2D graphical
12
+ user interfaces.
13
+
14
+ # GuiGeo2
15
+
16
+ ## GuiGeo2 vs GuiGeo
17
+
18
+ - Ruby 3+: minor changes
19
+ - Added workflow: Github testing with multiple versions of Ruby
20
+ - Added benchmarks
21
+ - Removed method disjoint
22
+ - Removed Guardfile
23
+ - Linter: using gem standard
24
+ - Restructuring
25
+ - Rspec replaced by Minitest
26
+ - Breaking change: rect & rect means intersection
27
+ - Breaking change: rect | rect means union
28
+
29
+ ## Installation
30
+
31
+ As usual:
32
+
33
+ ~~~~ruby
34
+ # Gemfile
35
+ ...
36
+ gem "guigeo2"
37
+ ...
38
+ ~~~~
39
+
40
+ and run "bundle install".
41
+
42
+ ## Usage (copied from GuiGeo)
43
+
44
+ Points are represented by X and Y coordinates:
45
+
46
+ Rectangles consist of two point objects.
47
+ One specifies the location of the rectangle - it's top-left corner.
48
+ The other specifies its size in terms of width then height.
49
+
50
+ ``` ruby
51
+ require "gui_geometry"
52
+ include GuiGeo2
53
+
54
+ # create point x == y == 0
55
+ point
56
+ # => point(0, 0)
57
+
58
+ # create a point x=3, y=4
59
+ my_point = point(3, 4)
60
+ # => point(3, 4)
61
+
62
+ [my_point.x, my_point.y]
63
+ # => [3, 4]
64
+
65
+ # create a rectangle - x, y, w, h form
66
+ rect(4, 5, 100, 80)
67
+ # => rect(4, 5, 100, 80)
68
+
69
+ # create rectangle - location, size form
70
+ my_rect = rect point(4, 5), point(100, 80)
71
+ # => rect(4, 5, 100, 80)
72
+
73
+ # create rectangle - size form (location defaults to 0,0
74
+ rect point(30, 50)
75
+ # => rect(0, 0, 30, 50)
76
+
77
+ # get loc and size:
78
+ [my_rect.loc, my_rect.size]
79
+ # => [point(4, 5), point(100, 80)]
80
+
81
+ # get x, y, width and height
82
+ [my_rect.x, my_rect.y, my_rect.w, my_rect.h]
83
+ # => [4, 5, 100, 80]
84
+
85
+ # get the 4 corners:
86
+ [my_rect.tl, my_rect.tr, my_rect.bl, my_rect.br]
87
+ # => [point(4, 5), point(104, 5), point(4, 85), point(104, 85)]
88
+ ```
89
+
90
+ To get access to min, max, bound, and minmax:
91
+
92
+ ```
93
+ include GuiGeo2::Tools
94
+
95
+ min(4, 5)
96
+ # => 4
97
+
98
+ max(4, 5)
99
+ # => 5
100
+
101
+ minmax(4, 5)
102
+ # => [4, 5]
103
+
104
+ bound(5, 4, 10)
105
+ # => 5
106
+ ```
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "rake"
2
+ require "rake/testtask"
3
+ require "bundler/gem_tasks"
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs.push "test"
7
+ t.pattern = "test/*_test.rb"
8
+ end
9
+
10
+ desc "Default: run unit tests."
11
+ task default: :test
@@ -0,0 +1,22 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "gui_geometry/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "gui_geometry2"
7
+ s.version = GuiGeo2::VERSION
8
+ s.authors = ["Dittmar Krall", "Shane Brinkman-Davis"]
9
+ s.email = ["dittmar.krall@matiq.com", "shanebdavis@gmail.com"]
10
+ s.description = "2D geometry specificly designed to support graphical user interfaces and bitmaps currently focsued on Point and Rectangle classes"
11
+ s.summary = "2D geometry specificly designed to support graphical user interfaces and bitmaps"
12
+ s.homepage = "https://github.com/shanebdavis/gui_geometry"
13
+ s.license = "MIT"
14
+
15
+ s.files = `git ls-files`.split($/)
16
+ s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+ s.required_ruby_version = ">= 3"
19
+
20
+ s.add_development_dependency "minitest"
21
+ s.add_development_dependency "simplecov"
22
+ end
@@ -0,0 +1,21 @@
1
+ class GuiGeo2::Point
2
+ include GuiGeo2::Tools
3
+
4
+ alias_method :w, :x
5
+ alias_method :width, :x
6
+ alias_method :col, :x
7
+ alias_method :column, :x
8
+
9
+ alias_method :h, :y
10
+ # alias_method :height, :y # reserved?
11
+ alias_method :line, :y
12
+ end
13
+
14
+ class GuiGeo2::Rectangle
15
+ include GuiGeo2::Tools
16
+
17
+ alias_method :width, :w
18
+ alias_method :height, :h
19
+ alias_method :|, :union
20
+ alias_method :&, :intersection
21
+ end
@@ -0,0 +1,31 @@
1
+ class GuiGeo2::Point < Struct.new(:x, :y)
2
+ include GuiGeo2::Tools
3
+
4
+ def initialize(*args)
5
+ self.x = self.y = 0
6
+ super if args.length != 0
7
+ raise ArgumentError unless valid?
8
+ end
9
+
10
+ def valid? = x.is_a?(Integer) && y.is_a?(Integer)
11
+
12
+ def +(other) = other.is_a?(Point) ? point(x + other.x, y + other.y) : point(x + other, y + other)
13
+ def -(other) = other.is_a?(Point) ? point(x - other.x, y - other.y) : point(x - other, y - other)
14
+ def *(other) = other.is_a?(Point) ? point(x * other.x, y * other.y) : point(x * other, y * other)
15
+ def /(other) = other.is_a?(Point) ? point(x / other.x, y / other.y) : point(x / other, y / other)
16
+
17
+ def >=(other) = x >= other.x && y >= other.y
18
+ def <=(other) = x <= other.x && y <= other.y
19
+ def >(other) = x > other.x && y > other.y
20
+ def <(other) = x < other.x && y < other.y
21
+
22
+ def min(b) = point(Tools.min(x, b.x), Tools.min(y, b.y))
23
+ def max(b) = point(Tools.max(x, b.x), Tools.max(y, b.y))
24
+ def bound(a, b) = point(Tools.bound(a.x, x, b.x), Tools.bound(a.y, y, b.y))
25
+
26
+ def area = x * y
27
+
28
+ def clone = point(clone_value(x), clone_value(y))
29
+ def inspect = "point(#{x}, #{y})"
30
+ def to_s = "(#{x}, #{y})"
31
+ end
@@ -0,0 +1,33 @@
1
+ class GuiGeo2::Rectangle < Struct.new(:loc, :size)
2
+ include GuiGeo2::Tools
3
+
4
+ def initialize(*args)
5
+ case args.length
6
+ when 0 then super(point, point)
7
+ when 1 then super(point, args[0])
8
+ when 2 then super(args[0], args[1])
9
+ when 4 then super(point(*args[0..1]), point(*args[2..3]))
10
+ else raise ArgumentError
11
+ end
12
+ raise ArgumentError unless valid?
13
+ end
14
+
15
+ def valid? = loc.valid? && size.valid?
16
+
17
+ def +(other)
18
+ other.is_a?(Point) ? rect(loc + other, size) : rect(loc + other.loc, size + other.size)
19
+ end
20
+
21
+ def -(other)
22
+ other.is_a?(Point) ? rect(loc - other, size) : rect(loc - other.loc, size - other.size)
23
+ end
24
+
25
+ def present? = w > 0 && h > 0
26
+ def blank? = !present?
27
+ def clone = rect loc.clone, size.clone
28
+
29
+ def area = size.area
30
+
31
+ def inspect = "rect" + to_s
32
+ def to_s = "(#{[loc.x, loc.y, size.x, size.y].join ", "})"
33
+ end
@@ -0,0 +1,57 @@
1
+ # rectangle 2
2
+
3
+ class GuiGeo2::Rectangle
4
+ include GuiGeo2::Tools
5
+
6
+ # val can be a Rectangle or Point
7
+ # returns a Rectangle or Point that is within this Rectangle
8
+ # For Rectangles, the size is only changed if it has to be
9
+ def bound(val)
10
+ case val
11
+ when Rectangle
12
+ r = val.clone
13
+ r.size = r.size.min(size)
14
+ r.loc = r.loc.bound(loc, loc + size - val.size)
15
+ r
16
+ when Point then (val - loc).bound(point, size) + loc
17
+ else raise ArgumentError, "wrong type: (#{val.class}) - Rectangle or Point expected"
18
+ end
19
+ end
20
+
21
+ def overlaps?(val)
22
+ case val
23
+ when nil then false
24
+ when Point
25
+ contains?(val)
26
+ when Rectangle
27
+ val.loc + val.size > loc && loc + size > val.loc
28
+ else raise ArgumentError, "wrong type: (#{val.class}) - Rectangle or Point expected"
29
+ end
30
+ end
31
+
32
+ def contains?(val)
33
+ case val
34
+ when nil then false
35
+ when Point
36
+ val >= loc && val < (loc + size)
37
+ when Rectangle
38
+ (self | val) == self
39
+ else raise ArgumentError, "wrong type: (#{val.class}) - Rectangle or Point expected"
40
+ end
41
+ end
42
+
43
+ def union(b)
44
+ return clone unless b
45
+ l = loc.min(b.loc)
46
+ s = br.max(b.br) - l
47
+ rect l, s
48
+ end
49
+
50
+ def intersection(b)
51
+ return self unless b
52
+ l = loc.max(b.loc)
53
+ s = br.min(b.br) - l
54
+ return rect unless s > point
55
+ rect l, s
56
+ end
57
+ end
@@ -0,0 +1,21 @@
1
+ class GuiGeo2::Rectangle
2
+ include GuiGeo2::Tools
3
+
4
+ def x = loc.x
5
+ def y = loc.y
6
+ def w = size.w
7
+ def h = size.h
8
+
9
+ def x_range = x...(x + w)
10
+ def y_range = y...(y + h)
11
+
12
+ def tl = loc
13
+ def tr = point(x + w, y)
14
+ def bl = point(x, y + h)
15
+ def br = loc + size
16
+
17
+ def left = loc.x
18
+ def top = loc.y
19
+ def right = loc.x + size.x
20
+ def bottom = loc.y + size.y
21
+ end
@@ -0,0 +1,23 @@
1
+ module GuiGeo2
2
+ module Tools
3
+ include ::GuiGeo2
4
+
5
+ def min(a, b) = (a < b) ? a : b
6
+ def max(a, b) = (a > b) ? a : b
7
+ def bound(a, bounded, c) = max(a, min(bounded, c))
8
+
9
+ def minmax(a, b) = (a <= b) ? [a, b] : [b, a]
10
+
11
+ def clone_value(v) = v
12
+ # def clone_value(v)
13
+ # case v
14
+ # when Integer, Float then v
15
+ # else v.clone
16
+ # end
17
+ # end
18
+
19
+ class << self
20
+ include GuiGeo2::Tools
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ module GuiGeo2
2
+ VERSION = "3.0.0" # 2026-08-20
3
+ # VERSION = "0.3.1"
4
+ end
@@ -0,0 +1,9 @@
1
+ %w[tools point rectangle rectangle2 rectangle3
2
+ alias version].each do |file|
3
+ require File.join(File.dirname(__FILE__), "gui_geometry", file)
4
+ end
5
+
6
+ module GuiGeo2
7
+ def point(...) = GuiGeo2::Point.new(...)
8
+ def rect(...) = GuiGeo2::Rectangle.new(...)
9
+ end
@@ -0,0 +1,29 @@
1
+ require "test_helper"
2
+
3
+ describe "Alias" do
4
+ include GuiGeo2::Tools
5
+
6
+ let(:p34) { point(3, 4) }
7
+ let(:r1234) { rect(1, 2, 3, 4) }
8
+ let(:r1235) { rect(1, 2, 3, 5) }
9
+
10
+ it "alias for Point x" do
11
+ assert_equal p34.x, p34.w
12
+ assert_equal p34.x, p34.width
13
+ assert_equal p34.x, p34.col
14
+ assert_equal p34.x, p34.column
15
+ end
16
+
17
+ it "alias for Point y" do
18
+ assert_equal p34.y, p34.h
19
+ # assert_equal p34.y, p34.height # reserved word?
20
+ assert_equal p34.y, p34.line
21
+ end
22
+
23
+ it "alias for rectanglex" do
24
+ assert_equal r1234.w, r1234.width
25
+ assert_equal r1234.h, r1234.height
26
+ assert_equal r1234 | r1235, r1234.union(r1235)
27
+ assert_equal r1234 & r1235, r1234.intersection(r1235)
28
+ end
29
+ end
@@ -0,0 +1,72 @@
1
+ # Benchmark 2 (rectangle3 rectangle tools)
2
+
3
+ require "test_helper"
4
+ require "benchmark"
5
+ require "benchmark/ips"
6
+
7
+ # return # outcomment to disable all benchmarks
8
+
9
+ describe "lib/gui_geometry" do
10
+ include GuiGeo2::Tools
11
+
12
+ let(:p1) { point(1, 2) }
13
+ let(:p3) { point(3, 5) }
14
+ let(:r0) { rect(0, 0, 0, 0) }
15
+ let(:rn) { rect(0, 1, 3, 5) }
16
+ let(:r10) { rect(0, 0, 10, 10) }
17
+
18
+ return # skip benchmarks; outcomment to run them
19
+ b_rectangle3 = 1 # outcomment to run this benchmark
20
+ b_rectangle = 1 # outcomment to run this benchmark
21
+ b_tools = 1 # outcomment to run this benchmark
22
+
23
+ it "runs" do
24
+ Benchmark.ips do |x|
25
+ if defined? b_rectangle3
26
+ x.report("rn.x") { rn.x }
27
+ x.report("rn.y") { rn.y }
28
+ x.report("rn.w") { rn.w }
29
+ x.report("rn.h") { rn.h }
30
+ x.report("rn.x_range") { rn.x_range }
31
+ x.report("rn.y_range") { rn.y_range }
32
+ x.report("r0.x_range") { r0.x_range }
33
+ x.report("r0.y_range") { r0.y_range }
34
+ x.report("rn.tl") { rn.tl }
35
+ x.report("rn.tr") { rn.tr }
36
+ x.report("rn.bl") { rn.bl }
37
+ x.report("rn.br") { rn.br }
38
+ x.report("rn.left") { rn.left }
39
+ x.report("rn.top") { rn.top }
40
+ x.report("rn.right") { rn.right }
41
+ x.report("rn.bottom") { rn.bottom }
42
+ end
43
+ if defined? b_rectangle
44
+ x.report("rect") { rect }
45
+ x.report("rect(p3)") { rect(p3) }
46
+ x.report("rect(point, point)") { rect(point, point) }
47
+ x.report("rect(0, 0, 0, 0)") { rect(0, 0, 0, 0) }
48
+ x.report("rn.valid?") { rn.valid? }
49
+ x.report("rn + p3") { rn + p3 }
50
+ x.report("rn + rn") { rn + rn }
51
+ x.report("rn - p3") { rn - p3 }
52
+ x.report("rn - r10") { rn - r10 }
53
+ x.report("rn.present?") { rn.present? }
54
+ x.report("rn.blank?") { rn.blank? }
55
+ x.report("rn.clone") { rn.clone }
56
+ x.report("rn.area") { rn.area }
57
+ x.report("rn.inspect") { rn.inspect }
58
+ x.report("rn.to_s") { rn.to_s }
59
+ end
60
+ if defined? b_tools
61
+ x.report("min(4, 5)") { min(4, 5) }
62
+ x.report("max(4, 5)") { max(4, 5) }
63
+ x.report("bound(2, 5, 7)") { bound(2, 5, 7) }
64
+ x.report("minmax(4, 5)") { minmax(4, 5) }
65
+ x.report("point") { point }
66
+ x.report("rect") { rect }
67
+ end
68
+
69
+ x.compare!
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,77 @@
1
+ # Benchmark (alias point rectangle)
2
+
3
+ require "test_helper"
4
+ require "benchmark"
5
+ require "benchmark/ips"
6
+
7
+ # return # outcomment to disable all benchmarks
8
+
9
+ describe "lib/gui_geometry" do
10
+ include GuiGeo2::Tools
11
+
12
+ let(:p1) { point(1, 2) }
13
+ let(:p3) { point(3, 5) }
14
+ let(:r0) { rect(0, 0, 0, 0) }
15
+ let(:rn) { rect(0, 1, 3, 5) }
16
+ let(:r10) { rect(0, 0, 10, 10) }
17
+
18
+ return # skip benchmarks; outcomment to run them
19
+ b_alias = 1 # outcomment to run this benchmark
20
+ b_point = 1 # outcomment to run this benchmark
21
+ b_rectangle2 = 1 # outcomment to run this benchmark
22
+
23
+ it "runs" do
24
+ Benchmark.ips do |x|
25
+ if defined? b_alias
26
+ x.report("p1.w") { p1.w }
27
+ x.report("p1.h") { p1.h }
28
+ x.report("p1.width") { p1.width }
29
+ # x.report("p1.height") { p1.heigth } # reserved?
30
+ x.report("p1.col") { p1.col }
31
+ x.report("p1.column") { p1.column }
32
+ x.report("p1.line") { p1.line }
33
+
34
+ x.report("rn.width") { rn.width }
35
+ x.report("rn.height") { rn.height }
36
+ x.report("r0 | rn") { r0 | rn }
37
+ x.report("r0 & rn") { r0 & rn }
38
+ end
39
+ if defined? b_point
40
+ x.report("point") { point }
41
+ x.report("point(1, 2)") { point(1, 2) }
42
+ x.report("valid?") { p1.valid? }
43
+ x.report("p1 + p3") { p1 + p3 }
44
+ x.report("p1 - p3") { p1 - p3 }
45
+ x.report("p1 * p3") { p1 * p3 }
46
+ x.report("p1 / p3") { p1 / p3 }
47
+ x.report("p1 >= p3") { p1 >= p3 }
48
+ x.report("p1 > p3") { p1 > p3 }
49
+ x.report("p1 <= p3") { p1 <= p3 }
50
+ x.report("p1 < p3") { p1 < p3 }
51
+ x.report("p1.min(p3)") { p1.min(p3) }
52
+ x.report("p1.max(p3)") { p1.max(p3) }
53
+ x.report("p1.bound(p1, p3)") { p1.bound(p1, p3) }
54
+ x.report("p1.area") { p1.area }
55
+ x.report("p1.clone") { p1.clone }
56
+ x.report("p1.inspect") { p1.inspect }
57
+ x.report("p1.to_s") { p1.to_s }
58
+ end
59
+ if defined? b_rectangle2
60
+ x.report("rn.bound(p1)") { rn.bound(p1) }
61
+ x.report("rn.bound(r10)") { rn.bound(r10) }
62
+ x.report("r10.overlaps?(nil)") { r10.overlaps?(nil) }
63
+ x.report("r10.overlaps?(p1)") { r10.overlaps?(p1) }
64
+ x.report("r10.overlaps?(rn)") { r10.overlaps?(rn) }
65
+ x.report("r10.contains?(nil)") { r10.contains?(nil) }
66
+ x.report("r10.contains?(p1)") { r10.contains?(p1) }
67
+ x.report("r10.contains?(rn)") { r10.contains?(rn) }
68
+ x.report("r10.union(nil)") { r10.union(nil) }
69
+ x.report("r10.union(rn)") { r10.union(rn) }
70
+ x.report("r10.intersection(nil)") { r10.intersection(nil) }
71
+ x.report("r10.intersection(rn)") { r10.intersection(rn) }
72
+ end
73
+
74
+ x.compare!
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,124 @@
1
+ require "test_helper"
2
+
3
+ describe "Point" do
4
+ include GuiGeo2::Tools
5
+
6
+ let(:p34) { point(3, 4) }
7
+
8
+ it "init" do
9
+ assert_equal point(0, 0), point
10
+ end
11
+
12
+ it "invalid init" do
13
+ assert_raises(ArgumentError) { point("1", 2) }
14
+ assert_raises(ArgumentError) { point(1.1, 2) }
15
+ assert_raises(ArgumentError) { point(1, :Y2) }
16
+ assert_raises(ArgumentError) { point(1) }
17
+ end
18
+
19
+ it "valid?" do
20
+ assert p34.valid?
21
+ end
22
+
23
+ it "+" do
24
+ assert_equal point(4, 6), (point(1, 2) + point(3, 4))
25
+ assert_equal point(4, 5), (point(1, 2) + 3)
26
+ end
27
+
28
+ it "-" do
29
+ assert_equal point(6, 4), (point(9, 8) - point(3, 4))
30
+ assert_equal point(6, 5), (point(9, 8) - 3)
31
+ end
32
+
33
+ it "*" do
34
+ assert_equal point(27, 32), (point(9, 8) * point(3, 4))
35
+ assert_equal point(27, 24), (point(9, 8) * 3)
36
+ end
37
+
38
+ it "/" do
39
+ assert_equal point(9, 8), (point(36, 24) / point(4, 3))
40
+ assert_equal point(18, 12), (point(36, 24) / 2)
41
+ end
42
+
43
+ it "==" do
44
+ assert p34 == point(3, 4)
45
+ refute point(3, 4) == point(2, 4)
46
+ refute point(3, 4) == point(3, 3)
47
+ end
48
+
49
+ it ">=" do
50
+ assert p34 >= point(3, 4)
51
+ refute point(2, 4) >= point(3, 4)
52
+ refute point(3, 3) >= point(3, 4)
53
+ refute point(3, 4) >= point(4, 4)
54
+ refute point(3, 4) >= point(3, 5)
55
+ end
56
+
57
+ it "<=" do
58
+ assert p34 <= point(3, 4)
59
+ refute point(3, 4) <= point(2, 4)
60
+ refute point(3, 4) <= point(3, 3)
61
+ refute point(4, 4) <= point(3, 4)
62
+ refute point(3, 5) <= point(3, 4)
63
+ end
64
+
65
+ it ">" do
66
+ assert point(4, 5) > point(3, 4)
67
+ refute point(3, 5) > point(3, 4)
68
+ refute point(4, 4) > point(3, 4)
69
+ refute point(4, 5) > point(4, 4)
70
+ refute point(4, 5) > point(3, 5)
71
+ end
72
+
73
+ it "<" do
74
+ assert p34 < point(4, 5)
75
+ refute point(3, 4) < point(3, 5)
76
+ refute point(3, 4) < point(4, 4)
77
+ refute point(4, 4) < point(4, 5)
78
+ refute point(3, 5) < point(4, 5)
79
+ end
80
+
81
+ it "min" do
82
+ assert_equal point(5, 5), point(5, 5).min(point(9, 9))
83
+ assert_equal point(5, 5), point(9, 9).min(point(5, 5))
84
+ assert_equal point(5, 5), point(9, 5).min(point(5, 9))
85
+ assert_equal point(5, 5), point(5, 9).min(point(9, 5))
86
+ end
87
+
88
+ it "max" do
89
+ assert_equal point(9, 9), point(5, 5).max(point(9, 9))
90
+ assert_equal point(9, 9), point(9, 9).max(point(5, 5))
91
+ assert_equal point(9, 9), point(9, 5).max(point(5, 9))
92
+ assert_equal point(9, 9), point(5, 9).max(point(9, 5))
93
+ end
94
+
95
+ it "bound" do
96
+ assert_equal point(3, 4), point(3, 4).bound(point(1, 2), point(5, 6))
97
+ assert_equal point(3, 2), point(3, 0).bound(point(1, 2), point(5, 6))
98
+ assert_equal point(3, 6), point(3, 6).bound(point(1, 2), point(5, 6))
99
+ assert_equal point(1, 4), point(0, 4).bound(point(1, 2), point(5, 6))
100
+ assert_equal point(5, 4), point(6, 4).bound(point(1, 2), point(5, 6))
101
+ end
102
+
103
+ it ".area" do
104
+ assert_equal 12, p34.area
105
+ assert_equal 300, point(15, 20).area
106
+ assert_equal(-15, point(-5, 3).area)
107
+ end
108
+
109
+ it "clone basic point" do
110
+ p1 = point(1, 2)
111
+ p2 = p1.clone
112
+ assert_equal p2, p1
113
+ p2.x = 3
114
+ refute_equal p2, p1
115
+ end
116
+
117
+ it "inspect" do
118
+ assert_equal "point(3, 4)", p34.inspect
119
+ end
120
+
121
+ it "to_s" do
122
+ assert_equal "(3, 4)", p34.to_s
123
+ end
124
+ end
@@ -0,0 +1,110 @@
1
+ require "test_helper"
2
+
3
+ describe "Rectangle 2" do
4
+ include GuiGeo2::Tools
5
+
6
+ let(:r10) { rect(0, 0, 10, 10) }
7
+ let(:rn) { rect(0, 1, 3, 5) }
8
+ let(:p34) { point(3, 4) }
9
+ let(:p10) { point(10, 10) }
10
+
11
+ it "ArgumentError" do
12
+ assert_raises(ArgumentError) { rn.bound(1) }
13
+ assert_raises(ArgumentError) { rn.overlaps?(1.23) }
14
+ assert_raises(ArgumentError) { rn.contains?("abc") }
15
+ end
16
+
17
+ it "contains?" do
18
+ assert rect(0, 0, 10, 10).contains?(rect(2, 2, 5, 5))
19
+ refute rect(0, 0, 10, 10).contains?(rect(8, 2, 5, 5))
20
+ end
21
+
22
+ it ".overlap?" do
23
+ # solidly overlapping
24
+ assert rect(0, 0, 10, 10).overlaps?(rect(0, 0, 10, 10))
25
+ assert rect(0, 0, 10, 10).overlaps?(rect(0, 5, 10, 10))
26
+ assert rect(0, 0, 10, 10).overlaps?(rect(5, 0, 10, 10))
27
+
28
+ # just below, just to the right, just above, just to the left
29
+ refute rect(0, 0, 10, 10).overlaps?(rect(10, 0, 10, 10))
30
+ refute rect(0, 0, 10, 10).overlaps?(rect(0, 10, 10, 10))
31
+ refute rect(10, 0, 10, 10).overlaps?(rect(0, 0, 10, 10))
32
+ refute rect(0, 10, 10, 10).overlaps?(rect(0, 0, 10, 10))
33
+
34
+ # below, right, above, left
35
+ refute rect(0, 0, 10, 10).overlaps?(rect(11, 0, 10, 10))
36
+ refute rect(0, 0, 10, 10).overlaps?(rect(0, 11, 10, 10))
37
+ refute rect(11, 0, 10, 10).overlaps?(rect(0, 0, 10, 10))
38
+ refute rect(0, 11, 10, 10).overlaps?(rect(0, 0, 10, 10))
39
+
40
+ # just overlapping below, right, above, left
41
+ assert rect(0, 0, 10, 10).overlaps?(rect(9, 0, 10, 10))
42
+ assert rect(0, 0, 10, 10).overlaps?(rect(0, 9, 10, 10))
43
+ assert rect(9, 0, 10, 10).overlaps?(rect(0, 0, 10, 10))
44
+ assert rect(0, 9, 10, 10).overlaps?(rect(0, 0, 10, 10))
45
+ end
46
+
47
+ it ".union" do
48
+ assert_equal rect(0, 0, 10, 15), rect(0, 0, 10, 10) | rect(0, 5, 10, 10)
49
+ assert_equal rect(0, 0, 15, 10), rect(0, 0, 10, 10) | rect(5, 0, 10, 10)
50
+ assert_equal rect(0, 0, 30, 30), rect(20, 20, 10, 10) | rect(0, 0, 10, 10)
51
+ end
52
+
53
+ it ".intersection" do
54
+ r10 = rect(0, 0, 10, 10)
55
+ assert_equal rect(0, 0, 10, 10), r10 & rect(0, 0, 10, 10)
56
+ assert_equal rect(0, 5, 10, 5), r10 & rect(0, 5, 10, 10)
57
+ assert_equal rect(5, 0, 5, 10), r10 & rect(5, 0, 10, 10)
58
+ assert_equal rect(0, 0, 0, 0), r10 & rect(10, 0, 10, 10)
59
+ assert_equal rect(0, 0, 5, 5), r10 & rect(-5, -5, 10, 10)
60
+ end
61
+
62
+ it "default intersection and union" do
63
+ assert_equal rect(0, 0, 10, 10), rect(0, 0, 10, 10) | nil
64
+ assert_equal rect(0, 0, 10, 10), rect(0, 0, 10, 10) & nil
65
+ end
66
+
67
+ it ".bound(point)" do
68
+ r = rect(5, 10, 15, 20)
69
+ assert_equal point(5, 10), r.bound(point(5, 10))
70
+ assert_equal point(20, 30), r.bound(point(20, 30))
71
+ assert_equal point(5, 30), r.bound(point(5, 31))
72
+ assert_equal point(20, 10), r.bound(point(21, 10))
73
+ assert_equal point(5, 10), r.bound(point(5, 10))
74
+ assert_equal point(5, 10), r.bound(point(5, 9))
75
+ assert_equal point(5, 10), r.bound(point(4, 10))
76
+ end
77
+
78
+ it ".bound(smaller_rect)" do
79
+ r1 = rect(5, 10, 15, 20)
80
+ assert_equal rect(5, 10, 5, 5), r1.bound(rect(5, 0, 5, 5))
81
+ assert_equal rect(5, 10, 5, 5), r1.bound(rect(0, 10, 5, 5))
82
+ assert_equal rect(5, 25, 5, 5), r1.bound(rect(0, 30, 5, 5))
83
+ assert_equal rect(15, 10, 5, 5), r1.bound(rect(30, 0, 5, 5))
84
+ assert_equal rect(5, 10, 15, 5), r1.bound(rect(0, 0, 20, 5))
85
+ end
86
+
87
+ it ".overlaps? point" do
88
+ r1 = rect(5, 10, 15, 20)
89
+ assert r1.overlaps?(point(10, 10))
90
+ refute r1.overlaps?(point(20, 10))
91
+ refute r1.overlaps?(point(10, 30))
92
+ refute r1.overlaps?(point(5, 9))
93
+ refute r1.overlaps?(point(4, 10))
94
+ end
95
+
96
+ it ".contains? point" do
97
+ r1 = rect(5, 10, 15, 20)
98
+ assert r1.contains?(point(10, 10))
99
+ refute r1.contains?(point(20, 10))
100
+ refute r1.contains?(point(10, 30))
101
+ refute r1.contains?(point(5, 9))
102
+ refute r1.contains?(point(4, 10))
103
+ end
104
+
105
+ it ".contains? and .overlaps? with nil" do
106
+ r1 = rect(5, 10, 15, 20)
107
+ refute r1.overlaps?(nil)
108
+ refute r1.contains?(nil)
109
+ end
110
+ end
@@ -0,0 +1,36 @@
1
+ require "test_helper"
2
+
3
+ describe "Rectangle 3" do
4
+ include GuiGeo2::Tools
5
+
6
+ let(:r0) { rect(0, 0, 0, 0) }
7
+ let(:rn) { rect(0, 1, 3, 5) }
8
+
9
+ it "x y w h" do
10
+ assert_equal 0, rn.x
11
+ assert_equal 1, rn.y
12
+ assert_equal 3, rn.w
13
+ assert_equal 5, rn.h
14
+ end
15
+
16
+ it ".y_range and .x_range" do
17
+ assert_equal (0...3), rn.x_range
18
+ assert_equal (1...6), rn.y_range
19
+ assert_equal (0...0), r0.x_range
20
+ assert_equal (0...0), r0.y_range
21
+ end
22
+
23
+ it "tl br bl tr" do
24
+ assert_equal point(0, 1), rn.tl
25
+ assert_equal point(3, 1), rn.tr
26
+ assert_equal point(0, 6), rn.bl
27
+ assert_equal point(3, 6), rn.br
28
+ end
29
+
30
+ it "left top right bottom" do
31
+ assert_equal 0, rn.left
32
+ assert_equal 1, rn.top
33
+ assert_equal 3, rn.right
34
+ assert_equal 6, rn.bottom
35
+ end
36
+ end
@@ -0,0 +1,75 @@
1
+ require "test_helper"
2
+
3
+ describe "Rectangle" do
4
+ include GuiGeo2::Tools
5
+
6
+ let(:r0) { rect(0, 0, 0, 0) }
7
+ let(:r10) { rect(0, 0, 10, 10) }
8
+ let(:rn) { rect(0, 1, 3, 5) }
9
+ let(:p34) { point(3, 4) }
10
+ let(:p10) { point(10, 10) }
11
+
12
+ it "init" do
13
+ assert_equal r0, rect
14
+ assert_equal r10, rect(p10)
15
+ assert_equal r0, rect(point, point)
16
+ assert_equal r0, rect(0, 0, 0, 0)
17
+ end
18
+
19
+ it "invalid init" do
20
+ assert_raises { rect(1) }
21
+ assert_raises { rect(1, 2) }
22
+ assert_raises { rect(1, 2, 3) }
23
+ end
24
+
25
+ it "valid?" do
26
+ assert rect.valid?
27
+ assert rn.valid?
28
+ end
29
+
30
+ it "+" do
31
+ assert_equal rect(3, 5, 3, 5), rn + p34
32
+ assert_equal rect(0, 2, 6, 10), rn + rn
33
+ end
34
+
35
+ it "-" do
36
+ assert_equal rect(-3, -3, 3, 5), rn - p34
37
+ assert_equal r0, rn - rn
38
+ assert_equal rect(0, 1, -7, -5), rn - r10
39
+ end
40
+
41
+ it ".present?" do
42
+ assert rect(0, 0, 1, 1).present?
43
+ refute rect(0, 0, 1, 0).present?
44
+ refute rect(0, 0, 0, 1).present?
45
+ refute rect(0, 0, 0, 0).present?
46
+ end
47
+
48
+ it ".blank?" do
49
+ refute rect(0, 0, 1, 1).blank?
50
+ assert rect(0, 0, 1, 0).blank?
51
+ assert rect(0, 0, 0, 1).blank?
52
+ assert rect(0, 0, 0, 0).blank?
53
+ end
54
+
55
+ it "clone" do
56
+ r1 = rect(1, 2, 3, 4)
57
+ r2 = r1.clone
58
+ assert_equal r2, r1
59
+ refute_equal r2.object_id, r1.object_id
60
+ refute_equal r2.loc.object_id, r1.loc.object_id
61
+ refute_equal r2.size.object_id, r1.size.object_id
62
+ end
63
+
64
+ it ".area" do
65
+ assert_equal 300, rect(5, 10, 15, 20).area
66
+ end
67
+
68
+ it "inspect" do
69
+ assert_equal "rect(0, 0, 0, 0)", rect.inspect
70
+ end
71
+
72
+ it "to_s" do
73
+ assert_equal "(0, 1, 3, 5)", rn.to_s
74
+ end
75
+ end
@@ -0,0 +1,10 @@
1
+ if ENV["COVERAGE"]
2
+ require "simplecov"
3
+ SimpleCov.start do
4
+ skip "/test/"
5
+ end
6
+ end
7
+
8
+ require "minitest/autorun"
9
+ require File.join(File.dirname(__FILE__), "..", "lib", "gui_geometry")
10
+ require "ricecream"
@@ -0,0 +1,32 @@
1
+ require "test_helper"
2
+
3
+ describe "Tools" do
4
+ include GuiGeo2::Tools
5
+
6
+ it "min" do
7
+ assert_equal 4, min(4, 5)
8
+ assert_equal 4, min(5, 4)
9
+ end
10
+
11
+ it "max" do
12
+ assert_equal 5, max(4, 5)
13
+ assert_equal 5, max(5, 4)
14
+ end
15
+
16
+ it "bound" do
17
+ assert_equal 5, bound(2, 5, 7)
18
+ assert_equal 2, bound(2, 1, 7)
19
+ assert_equal 7, bound(2, 8, 7)
20
+ assert_equal 2, bound(2, 8, 1)
21
+ end
22
+
23
+ it "minmax" do
24
+ assert_equal [4, 5], minmax(4, 5)
25
+ assert_equal [4, 5], minmax(5, 4)
26
+ end
27
+
28
+ it "easy constructors" do
29
+ assert_kind_of GuiGeo2::Point, point
30
+ assert_kind_of GuiGeo2::Rectangle, rect
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gui_geometry2
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Dittmar Krall
8
+ - Shane Brinkman-Davis
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: simplecov
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: 2D geometry specificly designed to support graphical user interfaces
42
+ and bitmaps currently focsued on Point and Rectangle classes
43
+ email:
44
+ - dittmar.krall@matiq.com
45
+ - shanebdavis@gmail.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - ".github/workflows/rake.yml"
51
+ - ".gitignore"
52
+ - ".ruby-version"
53
+ - ".watchr"
54
+ - Gemfile
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - gui_geometry.gemspec
59
+ - lib/gui_geometry.rb
60
+ - lib/gui_geometry/alias.rb
61
+ - lib/gui_geometry/point.rb
62
+ - lib/gui_geometry/rectangle.rb
63
+ - lib/gui_geometry/rectangle2.rb
64
+ - lib/gui_geometry/rectangle3.rb
65
+ - lib/gui_geometry/tools.rb
66
+ - lib/gui_geometry/version.rb
67
+ - test/alias_test.rb
68
+ - test/benchmark2_test.rb
69
+ - test/benchmark_test.rb
70
+ - test/point_test.rb
71
+ - test/rectangle2_test.rb
72
+ - test/rectangle3_test.rb
73
+ - test/rectangle_test.rb
74
+ - test/test_helper.rb
75
+ - test/tools_test.rb
76
+ homepage: https://github.com/shanebdavis/gui_geometry
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '3'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubygems_version: 4.0.16
95
+ specification_version: 4
96
+ summary: 2D geometry specificly designed to support graphical user interfaces and
97
+ bitmaps
98
+ test_files: []