perfect-shape 0.4.0 → 0.5.0

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: 13f257899f946daccf27fa951ed4208ce8143d2060b24fcb6198ba0e8f738646
4
- data.tar.gz: 1f9a0d7a1f210da0ee0e7b88514352b7d90c7893b05fe9b84145672989cd8eae
3
+ metadata.gz: ea11a066d120228aeb5889877909e17d93022e44e9c46899088bf97e52a328a6
4
+ data.tar.gz: 2d9f3031bd0edfa073d20c6c8f8d56541aa473ef92335f6606b88fbe0a9b39f4
5
5
  SHA512:
6
- metadata.gz: 2af7d835fdaf126b8ebb630fbc08400aab9a7b464c5d18ad3f09035f142940bb1db1fbe4c0a2a1bc33bf4a773f2ce920fb34e36d57a191143020cdd36357b483
7
- data.tar.gz: 693a20f1d100e70a8d429c8c02fddcfbdb0b2f2507cff92a0ddbc8c962db7758be5cee94df954ba5a89bba7619bdd9b2ee95b31b17896289e31d90a22d7eeb53
6
+ metadata.gz: 8025f51a536223a337d10b8a3b0bb9cd66aefe37543d24108aa002d719c4eb123a5b19d89b00157a85054bd614f92bdaf944562efbbecf14a93ab6d9c0a6481c
7
+ data.tar.gz: 06701161fbe42ec6afe1f19d9ece0db38d44db679702ea0db420fc260fa19526a2d2b4475c5aaa0d6f0500260ad48ad7267b4da1ec626153749d70175c50e523
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.5.0
4
+
5
+ - `Line#intersect?(rectangle)`
6
+ - `Rectangle#out_state(x_or_point, y = nil)`
7
+
3
8
  ## 0.4.0
4
9
 
5
10
  - `PerfectShape::AffineTransform#new`
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # Perfect Shape 0.4.0
1
+ # Perfect Shape 0.5.0
2
2
  ## Geometric Algorithms
3
3
  [![Gem Version](https://badge.fury.io/rb/perfect-shape.svg)](http://badge.fury.io/rb/perfect-shape)
4
4
  [![Test](https://github.com/AndyObtiva/perfect-shape/actions/workflows/ruby.yml/badge.svg)](https://github.com/AndyObtiva/perfect-shape/actions/workflows/ruby.yml)
5
5
 
6
- [`PerfectShape`](https://rubygems.org/gems/perfect-shape) 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](#perfectshapepoint) in popular geometry shapes such as [rectangle](#perfectshaperectangle), [square](#perfectshapesquare), [arc](#perfectshapearc) (open, chord, and pie), [ellipse](#perfectshapeellipse), [circle](#perfectshapecircle), [polygon](#perfectshapepolygon), and [paths](#perfectshapepath) containing [lines](#perfectshapeline), [quadratic bézier curves](#perfectshapequadraticbeziercurve), and [cubic bezier curves](#perfectshapecubicbeziercurve), potentially with [affine transforms](#perfectshapeaffinetransform) applied like translation, scale, rotation, shear/skew, and inversion (including both [Ray Casting Algorithm](https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm), aka [Even-odd Rule](https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule), and [Winding Number Algorithm](https://en.wikipedia.org/wiki/Point_in_polygon#Winding_number_algorithm), aka [Nonzero Rule](https://en.wikipedia.org/wiki/Nonzero-rule)).
6
+ [`PerfectShape`](https://rubygems.org/gems/perfect-shape) is a collection of pure Ruby geometric algorithms that are mostly useful for GUI (Graphical User Interface) manipulation like checking viewport rectangle intersection or containment of a mouse click [point](#perfectshapepoint) in popular geometry shapes such as [rectangle](#perfectshaperectangle), [square](#perfectshapesquare), [arc](#perfectshapearc) (open, chord, and pie), [ellipse](#perfectshapeellipse), [circle](#perfectshapecircle), [polygon](#perfectshapepolygon), and [paths](#perfectshapepath) containing [lines](#perfectshapeline), [quadratic bézier curves](#perfectshapequadraticbeziercurve), and [cubic bezier curves](#perfectshapecubicbeziercurve), potentially with [affine transforms](#perfectshapeaffinetransform) applied like translation, scale, rotation, shear/skew, and inversion (including both [Ray Casting Algorithm](https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm), aka [Even-odd Rule](https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule), and [Winding Number Algorithm](https://en.wikipedia.org/wiki/Point_in_polygon#Winding_number_algorithm), aka [Nonzero Rule](https://en.wikipedia.org/wiki/Nonzero-rule)).
7
7
 
8
8
  Additionally, [`PerfectShape::Math`](#perfectshapemath) contains some purely mathematical algorithms, like [IEEE 754-1985 Remainder](https://en.wikipedia.org/wiki/IEEE_754-1985).
9
9
 
@@ -14,13 +14,13 @@ To ensure high accuracy, this library does all its mathematical operations with
14
14
  Run:
15
15
 
16
16
  ```
17
- gem install perfect-shape -v 0.4.0
17
+ gem install perfect-shape -v 0.5.0
18
18
  ```
19
19
 
20
20
  Or include in Bundler `Gemfile`:
21
21
 
22
22
  ```ruby
23
- gem 'perfect-shape', '~> 0.4.0'
23
+ gem 'perfect-shape', '~> 0.5.0'
24
24
  ```
25
25
 
26
26
  And, run:
@@ -220,6 +220,7 @@ Includes `PerfectShape::MultiPoint`
220
220
  - `#bounding_box`: bounding box is a rectangle with x = min x, y = min y, and width/height of shape
221
221
  - `#==(other)`: Returns `true` if equal to `other` or `false` otherwise
222
222
  - `#contain?(x_or_point, y=nil, outline: true, distance_tolerance: 0)`: checks if point lies on line, with a distance tolerance (0 by default). Distance tolerance provides a fuzz factor that for example enables GUI users to mouse-click-select a line shape more successfully. `outline` option makes no difference on line
223
+ - `#intersect?(rectangle)`: Returns `true` if intersecting with interior of rectangle or `false` otherwise. This is useful for GUI optimization checks of whether a shape appears in a GUI viewport rectangle and needs redrawing
223
224
  - `#relative_counterclockwise(x_or_point, y=nil)`: 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, 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)”.
224
225
  - `#point_distance(x_or_point, y=nil)`: Returns the distance from a point to a line segment.
225
226
 
@@ -362,6 +363,7 @@ Includes `PerfectShape::RectangularShape`
362
363
  - `#==(other)`: Returns `true` if equal to `other` or `false` otherwise
363
364
  - `#contain?(x_or_point, y=nil, outline: false, distance_tolerance: 0)`: checks if point is inside when `outline` is `false` or if point is on the outline when `outline` is `true`. `distance_tolerance` can be used as a fuzz factor when `outline` is `true`, for example, to help GUI users mouse-click-select a rectangle shape from its outline more successfully
364
365
  - `#edges`: edges of rectangle as `PerfectShape::Line` objects
366
+ - `#out_state(x_or_point, y = nil)`: Returns "out state" of specified point (x,y) (whether it lies to the left, right, top, bottom of rectangle). If point is outside rectangle, it returns a bit mask combination of `Rectangle::OUT_LEFT`, `Rectangle::OUT_RIGHT`, `Rectangle::OUT_TOP`, or `Rectangle::OUT_BOTTOM`. Otherwise, it returns `0` if point is inside the rectangle.
365
367
 
366
368
  Example:
367
369
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.5.0
@@ -22,6 +22,7 @@
22
22
  require 'perfect_shape/shape'
23
23
  require 'perfect_shape/point'
24
24
  require 'perfect_shape/multi_point'
25
+ require 'perfect_shape/rectangle'
25
26
 
26
27
  module PerfectShape
27
28
  class Line < Shape
@@ -241,5 +242,29 @@ module PerfectShape
241
242
  return unless x && y
242
243
  Line.point_crossings(points[0][0], points[0][1], points[1][0], points[1][1], x, y)
243
244
  end
245
+
246
+ def intersect?(rectangle)
247
+ x1 = points[0][0]
248
+ y1 = points[0][1]
249
+ x2 = points[1][0]
250
+ y2 = points[1][1]
251
+ out1 = out2 = nil
252
+ return true if (out2 = rectangle.out_state(x2, y2)) == 0
253
+ while (out1 = rectangle.out_state(x1, y1)) != 0
254
+ return false if (out1 & out2) != 0
255
+ if (out1 & (Rectangle::OUT_LEFT | Rectangle::OUT_RIGHT)) != 0
256
+ x = rectangle.x
257
+ x += rectangle.width if (out1 & Rectangle::OUT_RIGHT) != 0
258
+ y1 = y1 + (x - x1) * (y2 - y1) / (x2 - x1)
259
+ x1 = x
260
+ else
261
+ y = rectangle.y
262
+ y += rectangle.height if (out1 & Rectangle::OUT_BOTTOM) != 0
263
+ x1 = x1 + (y - y1) * (x2 - x1) / (y2 - y1)
264
+ y1 = y
265
+ end
266
+ end
267
+ true
268
+ end
244
269
  end
245
270
  end
@@ -28,6 +28,18 @@ module PerfectShape
28
28
  class Rectangle < Shape
29
29
  include RectangularShape
30
30
  include Equalizer.new(:x, :y, :width, :height)
31
+
32
+ # bitmask indicating a point lies to the left
33
+ OUT_LEFT = 1
34
+
35
+ # bitmask indicating a point lies above
36
+ OUT_TOP = 2
37
+
38
+ # bitmask indicating a point lies to the right
39
+ OUT_RIGHT = 4
40
+
41
+ # bitmask indicating a point lies below
42
+ OUT_BOTTOM = 8
31
43
 
32
44
  # Checks if rectangle contains point (two-number Array or x, y args)
33
45
  #
@@ -56,5 +68,32 @@ module PerfectShape
56
68
  Line.new(points: [[self.x, self.y + height], [self.x, self.y]])
57
69
  ]
58
70
  end
71
+
72
+ # Returns out state for specified point (x,y): (left, right, top, bottom)
73
+ #
74
+ # It can be 0 meaning not outside the rectangle,
75
+ # or if outside the rectangle, then a bit mask
76
+ # combination of OUT_LEFT, OUT_RIGHT, OUT_TOP, or OUT_BOTTOM
77
+ def out_state(x_or_point, y = nil)
78
+ x, y = Point.normalize_point(x_or_point, y)
79
+ return unless x && y
80
+
81
+ out = 0
82
+ if self.width <= 0
83
+ out |= OUT_LEFT | OUT_RIGHT
84
+ elsif x < self.x
85
+ out |= OUT_LEFT
86
+ elsif x > self.x + self.width
87
+ out |= OUT_RIGHT
88
+ end
89
+ if self.height <= 0
90
+ out |= OUT_TOP | OUT_BOTTOM
91
+ elsif y < self.y
92
+ out |= OUT_TOP
93
+ elsif y > self.y + self.height
94
+ out |= OUT_BOTTOM
95
+ end
96
+ out
97
+ end
59
98
  end
60
99
  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.4.0 ruby lib
5
+ # stub: perfect-shape 0.5.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "perfect-shape".freeze
9
- s.version = "0.4.0"
9
+ s.version = "0.5.0"
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 = "2022-01-16"
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 (open, chord, and pie), ellipse, circle, polygon, and paths containing lines, quadratic b\u00E9zier curves, and cubic bezier curves, potentially with affine transforms applied like translation, scale, rotation, shear/skew, and inversion (including both Ray Casting Algorithm, aka Even-odd Rule, and Winding Number Algorithm, aka Nonzero Rule). Additionally, it contains some purely mathematical algorithms like IEEEremainder (also known as IEEE-754 remainder).".freeze
14
+ s.date = "2022-01-18"
15
+ s.description = "Perfect Shape is a collection of pure Ruby geometric algorithms that are mostly useful for GUI manipulation like checking viewport rectangle intersection or containment of a mouse click point in popular geometry shapes such as rectangle, square, arc (open, chord, and pie), ellipse, circle, polygon, and paths containing lines, quadratic b\u00E9zier curves, and cubic bezier curves, potentially with affine transforms applied like translation, scale, rotation, shear/skew, and inversion (including both Ray Casting Algorithm, aka Even-odd Rule, and Winding Number Algorithm, aka Nonzero Rule). 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",
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.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-16 00:00:00.000000000 Z
11
+ date: 2022-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: equalizer
@@ -95,14 +95,14 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  description: Perfect Shape is a collection of pure Ruby geometric algorithms that
98
- are mostly useful for GUI manipulation like checking containment of a mouse click
99
- point in popular geometry shapes such as rectangle, square, arc (open, chord, and
100
- pie), ellipse, circle, polygon, and paths containing lines, quadratic bézier curves,
101
- and cubic bezier curves, potentially with affine transforms applied like translation,
102
- scale, rotation, shear/skew, and inversion (including both Ray Casting Algorithm,
103
- aka Even-odd Rule, and Winding Number Algorithm, aka Nonzero Rule). Additionally,
104
- it contains some purely mathematical algorithms like IEEEremainder (also known as
105
- IEEE-754 remainder).
98
+ are mostly useful for GUI manipulation like checking viewport rectangle intersection
99
+ or containment of a mouse click point in popular geometry shapes such as rectangle,
100
+ square, arc (open, chord, and pie), ellipse, circle, polygon, and paths containing
101
+ lines, quadratic bézier curves, and cubic bezier curves, potentially with affine
102
+ transforms applied like translation, scale, rotation, shear/skew, and inversion
103
+ (including both Ray Casting Algorithm, aka Even-odd Rule, and Winding Number Algorithm,
104
+ aka Nonzero Rule). Additionally, it contains some purely mathematical algorithms
105
+ like IEEEremainder (also known as IEEE-754 remainder).
106
106
  email: andy.am@gmail.com
107
107
  executables: []
108
108
  extensions: []