perfect-shape 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 00c1add66582b68b1c6ec2d15b91c9af7840daf97b7e40662210683690d1a082
4
- data.tar.gz: 2b789617e71a321cd7b736abfcfd59d7c46dbbf91fa0b4e2e5f581704e28527a
3
+ metadata.gz: 27a7fef31137e74569d2a21ccb631fc968b0d1b78897d85a67f958c27833b910
4
+ data.tar.gz: 2335d8343628c9b599ea20a25c83a8986ebdd45a9fcdfd027312ccf05d44bd0f
5
5
  SHA512:
6
- metadata.gz: 6c7b3efef675a42f6d33aae8d2d208e7224c44f9d8e64064dc9f18b0a3594b4cf2b3addb360376e5837f9478c5e61b18d85b989a16c122ed1d762f88c849075a
7
- data.tar.gz: 6b87d053a77eab1900c67ffb1a5800a878f9f06de7e9713d72f9ecedf5fc6e463e2cb885d1f6e1cfd7eca9eeb08b1321e6e97009564d6c4082a7a542db2d8ea2
6
+ metadata.gz: 62a9db0050089a036fda899a076e8b5467519e03208a39f3da7faa11e940124c3b71738a3c6ed02bd2b15fc64723e8e851c844e63a727196200ab698f4f3c2fb
7
+ data.tar.gz: 16ec103325e93f584f3c4831951da95e4f92e6489a20dfd23ced5ce6c05f7e9e508fd824b5f3daffd4b98f3b9a3fd6f26ec3d941cd111197bba0d043c5f26827
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.2
4
+
5
+ - `PerfectShape::Rectangle`
6
+ - `PerfectShape::Rectangle#contain?(x_or_point, y=nil)`
7
+
3
8
  ## 0.0.1
4
9
 
5
10
  - `PerfectShape::Math`
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
- # Perfect Shape 0.0.1
1
+ # Perfect Shape 0.0.2
2
2
  ## Geometric Algorithms
3
+ [![Gem Version](https://badge.fury.io/rb/perfect-shape.svg)](http://badge.fury.io/rb/perfect-shape)
3
4
 
4
- `PerfectShape` is a collection of pure Ruby geometric algorithms that are mostly useful for GUI (Graphical User Interface) manipulation like checking containment of a point in popular geometric shapes such as rectangle, square, arc, circle, polygon, polyline, and paths containing lines, bezier curves, and quadratic curves.
5
+ `PerfectShape` is a collection of pure Ruby geometric algorithms that are mostly useful for GUI (Graphical User Interface) manipulation like checking containment of a mouse click point in popular geometry shapes such as rectangle, square, arc, ellipse, circle, polygon, polyline, polybezier, and paths containing lines, bezier curves, and quadratic curves.
5
6
 
6
7
  Additionally, `PerfectShape::Math` contains some purely mathematical algorithms.
7
8
 
@@ -12,13 +13,13 @@ To ensure high accuracy, this library does all its mathematical operations with
12
13
  Run:
13
14
 
14
15
  ```
15
- gem install perfect-shape -v 0.0.1
16
+ gem install perfect-shape -v 0.0.2
16
17
  ```
17
18
 
18
19
  Or include in Bundler `Gemfile`:
19
20
 
20
21
  ```ruby
21
- gem 'perfect-shape', '~> 0.0.1'
22
+ gem 'perfect-shape', '~> 0.0.2'
22
23
  ```
23
24
 
24
25
  And, run:
@@ -37,7 +38,16 @@ bundle
37
38
 
38
39
  ### `PerfectShape::Line`
39
40
 
40
- - `::relative_ccw(x1, y1, x2, y2, px, py)`: Returns an indicator of where the specified point px,py lies with respect to the line segment from x1,y1 to x2,y2
41
+ - `::relative_ccw(x1, y1, x2, y2, px, py)`: Returns an indicator of where the specified point (px,py) lies with respect to the line segment from (x1,y1) to (x2,y2). The return value can be either 1, -1, or 0 and indicates in which direction the specified line must pivot around its first end point, (x1,y1), in order to point at the specified point (px,py). A return value of 1 indicates that the line segment must turn in the direction that takes the positive X axis towards the negative Y axis. In the default coordinate system used by Java 2D, this direction is counterclockwise. A return value of -1 indicates that the line segment must turn in the direction that takes the positive X axis towards the positive Y axis. In the default coordinate system, this direction is clockwise. A return value of 0 indicates that the point lies exactly on the line segment. Note that an indicator value of 0 is rare and not useful for determining collinearity because of floating point rounding issues. If the point is colinear with the line segment, but not between the end points, then the value will be -1 if the point lies “beyond (x1,y1)” or 1 if the point lies “beyond (x2,y2)”.
42
+
43
+ ### `PerfectShape::Rectangle`
44
+
45
+ - `::new(x: 0, y: 0, width: 1, height: 1)`: constructs a rectangle
46
+ - `#x`: top-left x
47
+ - `#y`: top-left y
48
+ - `#width`: width
49
+ - `#height`: height
50
+ - `#contain?(x_or_point, y=nil)`: checks if point inside
41
51
 
42
52
  ### `PerfectShape::Arc`
43
53
 
@@ -48,7 +58,16 @@ bundle
48
58
  - `#height`: height of arc
49
59
  - `#start`: start angle in degrees
50
60
  - `#extent`: extent angle in degrees
51
- - `#contain?(x_or_point, y=0)`: checks if point is in arc
61
+ - `#contain?(x_or_point, y=nil)`: checks if point is in arc
62
+
63
+ ## Process
64
+
65
+ [Glimmer Process](https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md)
66
+
67
+ ## Resources
68
+
69
+ - Rubydoc: https://www.rubydoc.info/gems/perfect-shape
70
+ - AWT Geom JavaDoc: https://docs.oracle.com/javase/8/docs/api/java/awt/geom/package-summary.html
52
71
 
53
72
  ## TODO
54
73
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/lib/perfect-shape.rb CHANGED
@@ -19,6 +19,8 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
+ $LOAD_PATH.unshift File.expand_path('.', __dir__)
23
+
22
24
  require 'bigdecimal'
23
25
 
24
26
  # Perfect Shape algorithms are mostly ported from java.awt.geom: https://docs.oracle.com/javase/8/docs/api/java/awt/geom/package-summary.html
@@ -19,40 +19,26 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
- require_relative 'line'
22
+ require 'perfect_shape/shape'
23
+ require 'perfect_shape/rectangular_shape'
24
+ require 'perfect_shape/line'
23
25
 
24
26
  module PerfectShape
25
27
  # Mostly ported from java.awt.geom: https://docs.oracle.com/javase/8/docs/api/java/awt/geom/Arc2D.html
26
- class Arc
28
+ class Arc < Shape
29
+ include RectangularShape
30
+
27
31
  TYPES = [:open, :chord, :pie]
28
- attr_accessor :type, :x, :y, :width, :height, :start, :extent
32
+ attr_accessor :type
33
+ attr_reader :start, :extent
29
34
 
30
35
  def initialize(type: :open, x: 0, y: 0, width: 1, height: 1, start: 0, extent: 360)
36
+ super(x: x, y: y, width: width, height: height)
31
37
  @type = type
32
- self.x = x
33
- self.y = y
34
- self.width = width
35
- self.height = height
36
38
  self.start = start
37
39
  self.extent = extent
38
40
  end
39
41
 
40
- def x=(value)
41
- @x = BigDecimal(value.to_s)
42
- end
43
-
44
- def y=(value)
45
- @y = BigDecimal(value.to_s)
46
- end
47
-
48
- def width=(value)
49
- @width = BigDecimal(value.to_s)
50
- end
51
-
52
- def height=(value)
53
- @height = BigDecimal(value.to_s)
54
- end
55
-
56
42
  def start=(value)
57
43
  @start = BigDecimal(value.to_s)
58
44
  end
@@ -62,11 +48,15 @@ module PerfectShape
62
48
  end
63
49
 
64
50
  # Checks if arc contains point denoted by point (two-number Array or x, y args)
51
+ #
52
+ # @param x The X coordinate of the point to test.
53
+ # @param y The Y coordinate of the point to test.
54
+ #
55
+ # @return {@code true} if the point lies within the bound of
56
+ # the arc, {@code false} if the point lies outside of the
57
+ # arc's bounds.
65
58
  def contain?(x_or_point, y = nil)
66
- x = x_or_point
67
- x, y = x if y.nil? && x_or_point.is_a?(Array) && x_or_point.size == 2
68
- x = BigDecimal(x.to_s)
69
- y = BigDecimal(y.to_s)
59
+ x, y = normalize_point(x_or_point, y)
70
60
  return unless x && y
71
61
  # Normalize the coordinates compared to the ellipse
72
62
  # having a center at 0,0 and a radius of 0.5.
@@ -105,6 +95,8 @@ module PerfectShape
105
95
  inarc ? !inside : inside
106
96
  end
107
97
 
98
+ # Determines whether or not the specified angle is within the
99
+ # angular extents of the arc.
108
100
  def contain_angle?(angle)
109
101
  ang_ext = self.extent
110
102
  backwards = ang_ext < 0.0
@@ -118,6 +110,8 @@ module PerfectShape
118
110
  (angle >= 0.0) && (angle < ang_ext)
119
111
  end
120
112
 
113
+ # Normalizes the specified angle into the range -180 to 180.
114
+ # TODO refactor/extract to Math class
121
115
  def normalize_degrees(angle)
122
116
  if angle > 180.0
123
117
  if angle <= (180.0 + 360.0)
@@ -19,33 +19,23 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
+ require 'perfect_shape/shape'
23
+
22
24
  module PerfectShape
23
25
  # Mostly ported from java.awt.geom: https://docs.oracle.com/javase/8/docs/api/java/awt/geom/Line2D.html
24
- class Line
26
+ class Line < Shape
25
27
  class << self
26
- # Returns an indicator of where the specified point
27
- # {@code (px,py)} lies with respect to the line segment from
28
- # {@code (x1,y1)} to {@code (x2,y2)}.
29
- # The return value can be either 1, -1, or 0 and indicates
30
- # in which direction the specified line must pivot around its
31
- # first end point, {@code (x1,y1)}, in order to point at the
32
- # specified point {@code (px,py)}.
33
- # <p>A return value of 1 indicates that the line segment must
34
- # turn in the direction that takes the positive X axis towards
35
- # the negative Y axis. In the default coordinate system used by
36
- # Java 2D, this direction is counterclockwise.
37
- # <p>A return value of -1 indicates that the line segment must
38
- # turn in the direction that takes the positive X axis towards
39
- # the positive Y axis. In the default coordinate system, this
40
- # direction is clockwise.
41
- # <p>A return value of 0 indicates that the point lies
42
- # exactly on the line segment. Note that an indicator value
43
- # of 0 is rare and not useful for determining collinearity
44
- # because of floating point rounding issues.
45
- # <p>If the point is colinear with the line segment, but
46
- # not between the end points, then the value will be -1 if the point
47
- # lies "beyond {@code (x1,y1)}" or 1 if the point lies
48
- # "beyond {@code (x2,y2)}".
28
+ # Returns an indicator of where the specified point (px,py) lies with respect to the line segment from
29
+ # (x1,y1) to (x2,y2).
30
+ #
31
+ # The return value can be either 1, -1, or 0 and indicates in which direction the specified line must pivot around its first end point, (x1,y1), in order to point at the specified point (px,py).
32
+ # A return value of 1 indicates that the line segment must turn in the direction that takes the positive X axis towards the negative Y axis. In the default coordinate system used by Java 2D, this direction is counterclockwise.
33
+ #
34
+ # A return value of -1 indicates that the line segment must turn in the direction that takes the positive X axis towards the positive Y axis. In the default coordinate system, this direction is clockwise.
35
+ #
36
+ # A return value of 0 indicates that the point lies exactly on the line segment. Note that an indicator value of 0 is rare and not useful for determining collinearity because of floating point rounding issues.
37
+ #
38
+ # If the point is colinear with the line segment, but not between the end points, then the value will be -1 if the point lies “beyond (x1,y1)” or 1 if the point lies “beyond (x2,y2)”.
49
39
  #
50
40
  # @param x1 the X coordinate of the start point of the
51
41
  # specified line segment
@@ -62,7 +52,6 @@ module PerfectShape
62
52
  # @return an integer that indicates the position of the third specified
63
53
  # coordinates with respect to the line segment formed
64
54
  # by the first two specified coordinates.
65
- # @since 1.2
66
55
  def relative_ccw(x1, y1, x2, y2, px, py)
67
56
  x2 -= x1;
68
57
  y2 -= y1;
@@ -1,6 +1,8 @@
1
1
  module PerfectShape
2
2
  # Perfect Shape Math utility methods
3
+ #
3
4
  # Mostly ported from java.lang.Math: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html
5
+ #
4
6
  # Also includes standard Ruby ::Math utility methods
5
7
  module Math
6
8
  class << self
@@ -15,16 +17,20 @@ module PerfectShape
15
17
  end
16
18
 
17
19
  # Computes the remainder operation on two arguments as prescribed by the IEEE 754 standard.
18
- # Algorithm: x – (round(x/y)*y).
20
+ #
21
+ # Algorithm is exactly: x – (round(x/y)*y)
22
+ #
19
23
  # The `round` part rounds to the nearest even number when it is a halfway between n & y (integer + 0.5 number)
24
+ #
20
25
  # The remainder value is mathematically equal to x - y × n, where n is the mathematical integer closest to the exact mathematical value of the quotient x/y, and if two mathematical integers are equally close to x/y, then n is the integer that is even. If the remainder is zero, its sign is the same as the sign of the first argument. Special cases:
26
+ #
21
27
  # If either argument is NaN, or the first argument is infinite, or the second argument is positive zero or negative zero, then the result is NaN.
28
+ #
22
29
  # If the first argument is finite and the second argument is infinite, then the result is the same as the first argument.
23
- # Parameters:
24
- # x - the dividend.
25
- # y - the divisor.
26
- # Returns:
27
- # the remainder when x is divided by y.
30
+ #
31
+ # @param x the dividend.
32
+ # @param y the divisor.
33
+ # @return the remainder when x is divided by y.
28
34
  def ieee754_remainder(x, y)
29
35
  x = BigDecimal(x.to_s)
30
36
  y = BigDecimal(y.to_s)
@@ -0,0 +1,44 @@
1
+ # Copyright (c) 2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'perfect_shape/shape'
23
+ require 'perfect_shape/rectangular_shape'
24
+
25
+ module PerfectShape
26
+ # Mostly ported from java.awt.geom: https://docs.oracle.com/javase/8/docs/api/java/awt/geom/Rectangle2D.html
27
+ class Rectangle < Shape
28
+ include RectangularShape
29
+
30
+ # Checks if rectangle contains point denoted by point (two-number Array or x, y args)
31
+ #
32
+ # @param x The X coordinate of the point to test.
33
+ # @param y The Y coordinate of the point to test.
34
+ #
35
+ # @return {@code true} if the point lies within the bound of
36
+ # the rectangle, {@code false} if the point lies outside of the
37
+ # rectangle's bounds.
38
+ def contain?(x_or_point, y = nil)
39
+ x, y = normalize_point(x_or_point, y)
40
+ return unless x && y
41
+ x.between?(@x, @x + @width) && y.between?(@y, @y + @height)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,57 @@
1
+ # Copyright (c) 2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module PerfectShape
23
+ # Mixin Module for Rectangular Shapes (having x, y, width, height)
24
+ # Can only be mixed into a class extending Shape or another module
25
+ module RectangularShape
26
+ attr_reader :x, :y, :width, :height
27
+
28
+ # Calls super before setting x, y, width, height
29
+ def initialize(x: 0, y: 0, width: 1, height: 1)
30
+ super()
31
+ self.x = x
32
+ self.y = y
33
+ self.width = width
34
+ self.height = height
35
+ end
36
+
37
+ # Sets x, normalizing to BigDecimal
38
+ def x=(value)
39
+ @x = BigDecimal(value.to_s)
40
+ end
41
+
42
+ # Sets y, normalizing to BigDecimal
43
+ def y=(value)
44
+ @y = BigDecimal(value.to_s)
45
+ end
46
+
47
+ # Sets width, normalizing to BigDecimal
48
+ def width=(value)
49
+ @width = BigDecimal(value.to_s)
50
+ end
51
+
52
+ # Sets height, normalizing to BigDecimal
53
+ def height=(value)
54
+ @height = BigDecimal(value.to_s)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,39 @@
1
+ # Copyright (c) 2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module PerfectShape
23
+ class Shape
24
+ # Normalizes point args whether two-number Array or x, y args returning
25
+ # normalized point array of two BigDecimal's
26
+ #
27
+ # @param x_or_point The point or X coordinate of the point to test.
28
+ # @param y The Y coordinate of the point to test.
29
+ #
30
+ # @return Array of x and y BigDecimal's representing point
31
+ def normalize_point(x_or_point, y = nil)
32
+ x = x_or_point
33
+ x, y = x if y.nil? && x_or_point.is_a?(Array) && x_or_point.size == 2
34
+ x = BigDecimal(x.to_s)
35
+ y = BigDecimal(y.to_s)
36
+ [x, y]
37
+ end
38
+ end
39
+ end
@@ -2,17 +2,17 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: perfect-shape 0.0.1 ruby lib
5
+ # stub: perfect-shape 0.0.2 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "perfect-shape".freeze
9
- s.version = "0.0.1"
9
+ s.version = "0.0.2"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Andy Maleh".freeze]
14
- s.date = "2021-12-06"
15
- s.description = "Perfect Shape is a collection of pure Ruby geometric algorithms that are mostly useful for GUI manipulation like checking containment of a point in popular geometric shapes such as rectangle, square, arc, circle, polygon, polyline, and paths containing lines, bezier curves, and quadratic curves. Additionally, it contains some purely mathematical algorithms like IEEEremainder (also known as IEEE-754 remainder).".freeze
14
+ s.date = "2021-12-11"
15
+ s.description = "Perfect Shape is a collection of pure Ruby geometric algorithms that are mostly useful for GUI manipulation like checking containment of a mouse click point in popular geometry shapes such as rectangle, square, arc, ellipse, circle, polygon, polyline, polybezier, and paths containing lines, bezier curves, and quadratic curves. Additionally, it contains some purely mathematical algorithms like IEEEremainder (also known as IEEE-754 remainder).".freeze
16
16
  s.email = "andy.am@gmail.com".freeze
17
17
  s.extra_rdoc_files = [
18
18
  "CHANGELOG.md",
@@ -20,24 +20,18 @@ Gem::Specification.new do |s|
20
20
  "README.md"
21
21
  ]
22
22
  s.files = [
23
- ".document",
24
- ".ruby-gemset",
25
- ".ruby-version",
26
23
  "CHANGELOG.md",
27
- "Gemfile",
28
- "Gemfile.lock",
29
24
  "LICENSE.txt",
30
25
  "README.md",
31
- "Rakefile",
32
- "TODO.md",
33
26
  "VERSION",
34
27
  "lib/perfect-shape.rb",
35
28
  "lib/perfect_shape/arc.rb",
36
29
  "lib/perfect_shape/line.rb",
37
30
  "lib/perfect_shape/math.rb",
38
- "perfect-shape.gemspec",
39
- "test/lib/perfect_shape/test_arc.rb",
40
- "test/lib/perfect_shape/test_math.rb"
31
+ "lib/perfect_shape/rectangle.rb",
32
+ "lib/perfect_shape/rectangular_shape.rb",
33
+ "lib/perfect_shape/shape.rb",
34
+ "perfect-shape.gemspec"
41
35
  ]
42
36
  s.homepage = "http://github.com/AndyObtiva/perfect-shape".freeze
43
37
  s.licenses = ["MIT".freeze]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perfect-shape
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-06 00:00:00.000000000 Z
11
+ date: 2021-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -81,10 +81,11 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  description: Perfect Shape is a collection of pure Ruby geometric algorithms that
84
- are mostly useful for GUI manipulation like checking containment of a point in popular
85
- geometric shapes such as rectangle, square, arc, circle, polygon, polyline, and
86
- paths containing lines, bezier curves, and quadratic curves. Additionally, it contains
87
- some purely mathematical algorithms like IEEEremainder (also known as IEEE-754 remainder).
84
+ are mostly useful for GUI manipulation like checking containment of a mouse click
85
+ point in popular geometry shapes such as rectangle, square, arc, ellipse, circle,
86
+ polygon, polyline, polybezier, and paths containing lines, bezier curves, and quadratic
87
+ curves. Additionally, it contains some purely mathematical algorithms like IEEEremainder
88
+ (also known as IEEE-754 remainder).
88
89
  email: andy.am@gmail.com
89
90
  executables: []
90
91
  extensions: []
@@ -93,24 +94,18 @@ extra_rdoc_files:
93
94
  - LICENSE.txt
94
95
  - README.md
95
96
  files:
96
- - ".document"
97
- - ".ruby-gemset"
98
- - ".ruby-version"
99
97
  - CHANGELOG.md
100
- - Gemfile
101
- - Gemfile.lock
102
98
  - LICENSE.txt
103
99
  - README.md
104
- - Rakefile
105
- - TODO.md
106
100
  - VERSION
107
101
  - lib/perfect-shape.rb
108
102
  - lib/perfect_shape/arc.rb
109
103
  - lib/perfect_shape/line.rb
110
104
  - lib/perfect_shape/math.rb
105
+ - lib/perfect_shape/rectangle.rb
106
+ - lib/perfect_shape/rectangular_shape.rb
107
+ - lib/perfect_shape/shape.rb
111
108
  - perfect-shape.gemspec
112
- - test/lib/perfect_shape/test_arc.rb
113
- - test/lib/perfect_shape/test_math.rb
114
109
  homepage: http://github.com/AndyObtiva/perfect-shape
115
110
  licenses:
116
111
  - MIT
data/.document DELETED
@@ -1,5 +0,0 @@
1
- lib/**/*.rb
2
- bin/*
3
- -
4
- features/**/*.feature
5
- LICENSE.txt
data/.ruby-gemset DELETED
@@ -1 +0,0 @@
1
- perfect-shape
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- ruby-3.0.2
data/Gemfile DELETED
@@ -1,14 +0,0 @@
1
- source "https://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
5
-
6
- # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
- group :development do
9
- gem "rdoc", "~> 3.12"
10
- gem "juwelier", "~> 2.1.0"
11
- gem 'minitest', '~> 5.14.4'
12
- gem 'puts_debuggerer', '~> 0.13.1'
13
- gem 'rake-tui', '> 0'
14
- end
data/Gemfile.lock DELETED
@@ -1,102 +0,0 @@
1
- GEM
2
- remote: https://rubygems.org/
3
- specs:
4
- addressable (2.8.0)
5
- public_suffix (>= 2.0.2, < 5.0)
6
- awesome_print (1.9.2)
7
- builder (3.2.4)
8
- descendants_tracker (0.0.4)
9
- thread_safe (~> 0.3, >= 0.3.1)
10
- faraday (1.8.0)
11
- faraday-em_http (~> 1.0)
12
- faraday-em_synchrony (~> 1.0)
13
- faraday-excon (~> 1.1)
14
- faraday-httpclient (~> 1.0.1)
15
- faraday-net_http (~> 1.0)
16
- faraday-net_http_persistent (~> 1.1)
17
- faraday-patron (~> 1.0)
18
- faraday-rack (~> 1.0)
19
- multipart-post (>= 1.2, < 3)
20
- ruby2_keywords (>= 0.0.4)
21
- faraday-em_http (1.0.0)
22
- faraday-em_synchrony (1.0.0)
23
- faraday-excon (1.1.0)
24
- faraday-httpclient (1.0.1)
25
- faraday-net_http (1.0.1)
26
- faraday-net_http_persistent (1.2.0)
27
- faraday-patron (1.0.0)
28
- faraday-rack (1.0.0)
29
- git (1.9.1)
30
- rchardet (~> 1.8)
31
- github_api (0.19.0)
32
- addressable (~> 2.4)
33
- descendants_tracker (~> 0.0.4)
34
- faraday (>= 0.8, < 2)
35
- hashie (~> 3.5, >= 3.5.2)
36
- oauth2 (~> 1.0)
37
- hashie (3.6.0)
38
- highline (2.0.3)
39
- json (1.8.6)
40
- juwelier (2.1.3)
41
- builder
42
- bundler (>= 1.13)
43
- git (>= 1.2.5)
44
- github_api
45
- highline (>= 1.6.15)
46
- nokogiri (>= 1.5.10)
47
- rake
48
- rdoc
49
- semver
50
- jwt (2.3.0)
51
- minitest (5.14.4)
52
- multi_json (1.15.0)
53
- multi_xml (0.6.0)
54
- multipart-post (2.1.1)
55
- nokogiri (1.12.5-x86_64-darwin)
56
- racc (~> 1.4)
57
- oauth2 (1.4.7)
58
- faraday (>= 0.8, < 2.0)
59
- jwt (>= 1.0, < 3.0)
60
- multi_json (~> 1.3)
61
- multi_xml (~> 0.5)
62
- rack (>= 1.2, < 3)
63
- pastel (0.8.0)
64
- tty-color (~> 0.5)
65
- public_suffix (4.0.6)
66
- puts_debuggerer (0.13.1)
67
- awesome_print (~> 1.9.2)
68
- racc (1.6.0)
69
- rack (2.2.3)
70
- rake (13.0.6)
71
- rake-tui (0.2.3)
72
- tty-prompt
73
- rchardet (1.8.0)
74
- rdoc (3.12.2)
75
- json (~> 1.4)
76
- ruby2_keywords (0.0.5)
77
- semver (1.0.1)
78
- thread_safe (0.3.6)
79
- tty-color (0.6.0)
80
- tty-cursor (0.7.1)
81
- tty-prompt (0.23.1)
82
- pastel (~> 0.8)
83
- tty-reader (~> 0.8)
84
- tty-reader (0.9.0)
85
- tty-cursor (~> 0.7)
86
- tty-screen (~> 0.8)
87
- wisper (~> 2.0)
88
- tty-screen (0.8.1)
89
- wisper (2.0.1)
90
-
91
- PLATFORMS
92
- x86_64-darwin-19
93
-
94
- DEPENDENCIES
95
- juwelier (~> 2.1.0)
96
- minitest (~> 5.14.4)
97
- puts_debuggerer (~> 0.13.1)
98
- rake-tui (> 0)
99
- rdoc (~> 3.12)
100
-
101
- BUNDLED WITH
102
- 2.2.31
data/Rakefile DELETED
@@ -1,46 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'rubygems'
4
- require 'bundler'
5
- begin
6
- Bundler.setup(:default, :development)
7
- rescue Bundler::BundlerError => e
8
- $stderr.puts e.message
9
- $stderr.puts "Run `bundle install` to install missing gems"
10
- exit e.status_code
11
- end
12
- require 'rake'
13
- require 'juwelier'
14
- Juwelier::Tasks.new do |gem|
15
- # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
16
- gem.name = "perfect-shape"
17
- gem.homepage = "http://github.com/AndyObtiva/perfect-shape"
18
- gem.license = "MIT"
19
- gem.summary = %Q{Perfect Shape - Geometric Algorithms}
20
- gem.description = %Q{Perfect Shape is a collection of pure Ruby geometric algorithms that are mostly useful for GUI manipulation like checking containment of a point in popular geometric shapes such as rectangle, square, arc, circle, polygon, polyline, and paths containing lines, bezier curves, and quadratic curves. Additionally, it contains some purely mathematical algorithms like IEEEremainder (also known as IEEE-754 remainder).}
21
- gem.email = "andy.am@gmail.com"
22
- gem.authors = ["Andy Maleh"]
23
-
24
- # dependencies defined in Gemfile
25
- end
26
- Juwelier::RubygemsDotOrgTasks.new
27
-
28
- require "rake/testtask"
29
-
30
- Rake::TestTask.new(:test) do |t|
31
- t.libs << "test"
32
- t.libs << "lib"
33
- t.test_files = FileList["test/**/test_*.rb"]
34
- end
35
-
36
- task :default => :test
37
-
38
- require 'rdoc/task'
39
- Rake::RDocTask.new do |rdoc|
40
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
-
42
- rdoc.rdoc_dir = 'rdoc'
43
- rdoc.title = "perfect-shape #{version}"
44
- rdoc.rdoc_files.include('README*')
45
- rdoc.rdoc_files.include('lib/**/*.rb')
46
- end
data/TODO.md DELETED
@@ -1,31 +0,0 @@
1
- # TODO
2
-
3
- ## Geometry
4
-
5
- Mostly inspired by java.awt.geom: https://docs.oracle.com/javase/8/docs/api/java/awt/geom/package-summary.html
6
-
7
- - Polygon
8
- - CubicCurve
9
- - QuadCurve
10
- - Line
11
- - Path: flexible shape which represents an arbitrary geometric path
12
- - GeneralPath: represents a geometric path constructed from straight lines, and quadratic and cubic (Bézier) curves. It can contain multiple subpaths.
13
- - Rectangle
14
- - RoundRectangle
15
- - Point
16
- - Ellipse
17
- - Polybezier
18
- - Polyline
19
- - Area: aggregate of multiple shapes
20
- - AffineTransform: represents a 2D affine transform that performs a linear mapping from 2D coordinates to other 2D coordinates that preserves the "straightness" and "parallelness" of lines.
21
-
22
- ## Miscellaneous
23
-
24
- - Include screenshots of the supported shapes in README
25
-
26
- ## Maybe
27
-
28
- - Consider the idea of having tests run in JRuby and check against java.awt.geom and compare result with perfect-shape
29
- - Consider contributing IEEEremainder to Ruby
30
- - Contribute this type of expectation: _(arc).must_be :contain?, *point to Minitest Expectations
31
- - Maybe contribute xit to minitest expectations
@@ -1,184 +0,0 @@
1
- require 'puts_debuggerer'
2
- require 'minitest/autorun'
3
-
4
- require_relative '../../../lib/perfect-shape'
5
-
6
- describe PerfectShape do
7
- describe PerfectShape::Arc do
8
- it 'constructs with chord type and dimensions' do
9
- arc = PerfectShape::Arc.new(type: :chord, x: 2, y: 3, width: 50, height: 60, start: 30, extent: 90)
10
-
11
- _(arc.type).must_equal :chord
12
- _(arc.y).must_equal 3
13
- _(arc.y).must_equal 3
14
- _(arc.width).must_equal 50
15
- _(arc.height).must_equal 60
16
- _(arc.start).must_equal 30
17
- _(arc.extent).must_equal 90
18
- end
19
-
20
- it 'constructs with open type defaults' do
21
- arc = PerfectShape::Arc.new
22
-
23
- _(arc.type).must_equal :open
24
- _(arc.x).must_equal 0
25
- _(arc.y).must_equal 0
26
- _(arc.width).must_equal 1
27
- _(arc.height).must_equal 1
28
- _(arc.start).must_equal 0
29
- _(arc.extent).must_equal 360
30
- end
31
-
32
- it 'updates attributes' do
33
- arc = PerfectShape::Arc.new
34
- arc.type = :chord
35
- arc.x = 2
36
- arc.y = 3
37
- arc.width = 50
38
- arc.height = 60
39
- arc.start = 30
40
- arc.extent = 90
41
-
42
- _(arc.type).must_equal :chord
43
- _(arc.y).must_equal 3
44
- _(arc.y).must_equal 3
45
- _(arc.width).must_equal 50
46
- _(arc.height).must_equal 60
47
- _(arc.start).must_equal 30
48
- _(arc.extent).must_equal 90
49
- end
50
-
51
- it 'contains point with chord type circle' do
52
- arc = PerfectShape::Arc.new(type: :chord, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
53
- point = [arc.x + arc.width / 2.0, arc.y + arc.height / 2.0]
54
-
55
- _(arc).must_be :contain?, point
56
- _(arc.contain?(point)).must_equal arc.contain?(*point)
57
- end
58
-
59
- it 'contains point with chord type arc' do
60
- arc = PerfectShape::Arc.new(type: :chord, x: 2, y: 3, width: 50.5, height: 60.75, start: 45, extent: 270)
61
- point = [arc.x + arc.width*3/4.0, arc.y + (arc.height / 2.0)]
62
-
63
- _(arc).must_be :contain?, point
64
- _(arc.contain?(point)).must_equal arc.contain?(*point)
65
- end
66
-
67
- it 'does not contain point within bounding box with chord type arc' do
68
- arc = PerfectShape::Arc.new(type: :chord, x: 2, y: 3, width: 67, height: 46, start: 45, extent: 270)
69
- point = [arc.x + arc.width*(3.9/4.0), arc.y + (arc.height / 2.0)]
70
-
71
- _(arc.contain?(point)).must_equal false
72
- end
73
-
74
- it 'does not contain point in center of chord type arc' do
75
- arc = PerfectShape::Arc.new(type: :chord, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 145)
76
- point = [arc.x + arc.width / 2.0, arc.y + arc.height / 2.0]
77
-
78
- _(arc.contain?(point)).must_equal false
79
- end
80
-
81
- it 'does not contain point within bounding box with chord type circle' do
82
- arc = PerfectShape::Arc.new(type: :chord, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
83
- point = [3.0, 4.0]
84
-
85
- _(arc.contain?(point)).must_equal false
86
- end
87
-
88
- it 'does not contain point outside bounding box with chord type circle' do
89
- arc = PerfectShape::Arc.new(type: :chord, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
90
- point = [1.0, 2.0]
91
-
92
- _(arc.contain?(point)).must_equal false
93
- end
94
-
95
- it 'contains point with open type circle' do
96
- arc = PerfectShape::Arc.new(type: :open, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
97
- point = [arc.x + arc.width / 2.0, arc.y + arc.height / 2.0]
98
-
99
- _(arc).must_be :contain?, point
100
- _(arc.contain?(point)).must_equal arc.contain?(*point)
101
- end
102
-
103
- it 'contains point with open type arc' do
104
- arc = PerfectShape::Arc.new(type: :open, x: 2, y: 3, width: 50.5, height: 60.75, start: 45, extent: 270)
105
- point = [arc.x + arc.width*3/4.0, arc.y + (arc.height / 2.0)]
106
-
107
- _(arc).must_be :contain?, point
108
- _(arc.contain?(point)).must_equal arc.contain?(*point)
109
- end
110
-
111
- it 'does not contain point within bounding box with open type arc' do
112
- arc = PerfectShape::Arc.new(type: :open, x: 2, y: 3, width: 67, height: 46, start: 45, extent: 270)
113
- point = [arc.x + arc.width*(3.9/4.0), arc.y + (arc.height / 2.0)]
114
-
115
- _(arc.contain?(point)).must_equal false
116
- end
117
-
118
- it 'does not contain point in center of open type arc' do
119
- arc = PerfectShape::Arc.new(type: :open, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 145)
120
- point = [arc.x + arc.width / 2.0, arc.y + arc.height / 2.0]
121
-
122
- _(arc.contain?(point)).must_equal false
123
- end
124
-
125
- it 'does not contain point within bounding box with open type circle' do
126
- arc = PerfectShape::Arc.new(type: :open, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
127
- point = [3.0, 4.0]
128
-
129
- _(arc.contain?(point)).must_equal false
130
- end
131
-
132
- it 'does not contain point outside bounding box with open type circle' do
133
- arc = PerfectShape::Arc.new(type: :open, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
134
- point = [1.0, 2.0]
135
-
136
- _(arc.contain?(point)).must_equal false
137
- end
138
-
139
- it 'contains point with pie type circle' do
140
- arc = PerfectShape::Arc.new(type: :pie, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
141
- point = [arc.x + arc.width / 2.0, arc.y + arc.height / 2.0]
142
-
143
- _(arc).must_be :contain?, point
144
- _(arc.contain?(point)).must_equal arc.contain?(*point)
145
- end
146
-
147
- it 'contains point in center of pie type arc' do
148
- arc = PerfectShape::Arc.new(type: :pie, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 145)
149
- point = [arc.x + arc.width / 2.0, arc.y + arc.height / 2.0]
150
-
151
- _(arc).must_be :contain?, point
152
- _(arc.contain?(point)).must_equal arc.contain?(*point)
153
- end
154
-
155
- it 'contains point with pie type arc' do
156
- arc = PerfectShape::Arc.new(type: :pie, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 145)
157
- point = [arc.x + arc.width / 2.0 + (arc.width / 4.0), arc.y + (arc.height / 2.0) - (arc.height / 4.0)]
158
-
159
- _(arc).must_be :contain?, point
160
- _(arc.contain?(point)).must_equal arc.contain?(*point)
161
- end
162
-
163
- it 'does not contain point within bounding box with pie type arc' do
164
- arc = PerfectShape::Arc.new(type: :pie, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 145)
165
- point = [arc.x + (arc.width / 2.0) - (arc.width / 4.0), arc.y + arc.height / 2.0]
166
-
167
- _(arc.contain?(point)).must_equal false
168
- end
169
-
170
- it 'does not contain point within bounding box with pie type circle' do
171
- arc = PerfectShape::Arc.new(type: :pie, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
172
- point = [3.0, 4.0]
173
-
174
- _(arc.contain?(point)).must_equal false
175
- end
176
-
177
- it 'does not contain point outside bounding box with pie type circle' do
178
- arc = PerfectShape::Arc.new(type: :pie, x: 2, y: 3, width: 50.5, height: 60.75, start: 0, extent: 360)
179
- point = [1.0, 2.0]
180
-
181
- _(arc.contain?(point)).must_equal false
182
- end
183
- end
184
- end
@@ -1,76 +0,0 @@
1
- require 'puts_debuggerer'
2
- require 'minitest/autorun'
3
-
4
- require_relative '../../../lib/perfect-shape'
5
-
6
- describe PerfectShape do
7
- describe PerfectShape::Math do
8
- describe '#ieee754_remainder' do
9
- it 'returns a negative number rounding ceiling' do
10
- result = PerfectShape::Math.ieee754_remainder(7.5, 4.5)
11
-
12
- _(result).must_equal -1.5
13
- end
14
-
15
- it 'returns a positive number rounding floor' do
16
- result = PerfectShape::Math.ieee754_remainder(7.5, 3.5)
17
-
18
- _(result).must_equal 0.5
19
- end
20
-
21
- it 'returns a positive number rounding halfway to floor even number' do
22
- result = PerfectShape::Math.ieee754_remainder(5, 10)
23
-
24
- _(result).must_equal 5
25
- end
26
-
27
- it 'returns a negative number rounding halfway to ceiling even number' do
28
- result = PerfectShape::Math.ieee754_remainder(15, 10)
29
-
30
- _(result).must_equal -5
31
- end
32
-
33
- it 'returns NaN for x=NaN' do
34
- result = PerfectShape::Math.ieee754_remainder(Float::NAN, 10)
35
-
36
- _(result).must_be :nan?
37
- end
38
-
39
- it 'returns NaN for x=Infinity' do
40
- result = PerfectShape::Math.ieee754_remainder(Float::INFINITY, 10)
41
-
42
- _(result).must_be :nan?
43
- end
44
-
45
- it 'returns NaN for y=NaN' do
46
- result = PerfectShape::Math.ieee754_remainder(10, Float::NAN)
47
-
48
- _(result).must_be :nan?
49
- end
50
-
51
- it 'returns NaN for y=0' do
52
- result = PerfectShape::Math.ieee754_remainder(10, 0)
53
-
54
- _(result).must_be :nan?
55
- end
56
-
57
- it 'returns NaN for y=+0.0' do
58
- result = PerfectShape::Math.ieee754_remainder(10, 0.0)
59
-
60
- _(result).must_be :nan?
61
- end
62
-
63
- it 'returns NaN for y=-0.0' do
64
- result = PerfectShape::Math.ieee754_remainder(10, -0.0)
65
-
66
- _(result).must_be :nan?
67
- end
68
-
69
- it 'returns x for y=Infinity' do
70
- result = PerfectShape::Math.ieee754_remainder(10, Float::INFINITY)
71
-
72
- _(result).must_equal 10
73
- end
74
- end
75
- end
76
- end