-
Notifications
You must be signed in to change notification settings - Fork 194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clickable arc issue#778 #1561
Open
estensland
wants to merge
12
commits into
shoes:main
Choose a base branch
from
estensland:Clickable-Arc-Issue#778
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Clickable arc issue#778 #1561
Changes from 11 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
1a3a3db
Issue #778 oval in bounds, fixed wrong link in comment
estensland c7d6b43
Issue #778 arc in bounds, Logic for both in the oval and above/below …
estensland 8033fa6
Issue #778 refactoring odd names
estensland 7e7e640
Issue #778 complex methods breakdown
estensland cc00ec8
Issue#778 appeasing rubocop
estensland 6521120
issue #778 ugly code but working state in need of refactor
estensland 1f79647
refactoring code for issue #778
estensland 5e31e15
fixed specs and rubocop
estensland c5410ef
Issue 778 arc within bounds specs and code refactoring
estensland f547194
merged with master and fixed conflicts
estensland d12f71f
fixed errors and added specs to catch it
estensland d486a7f
added comments and cleaned up ranges
estensland File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,9 @@ class Shoes | |
# the arc itself! | ||
# @note The angle passed in is measured in Radians starting at 90 degrees or the 3 o'clock position. | ||
class Arc < Common::ArtElement | ||
include Math | ||
# angle is the gradient angle used across all art elements | ||
# angle1/2 are the angles of the arc itself! | ||
style_with :angle1, :angle2, :art_styles, :center, :common_styles, :dimensions, :radius, :wedge | ||
STYLES = { wedge: false, fill: Shoes::COLORS[:black] }.freeze | ||
|
||
|
@@ -55,5 +58,221 @@ def center_point=(point) | |
self.top = point.y - (height * 0.5).to_i | ||
end | ||
end | ||
|
||
def radius_x | ||
@radius_x ||= width.to_f / 2 | ||
end | ||
|
||
def radius_y | ||
@radius_y ||= height.to_f / 2 | ||
end | ||
|
||
def middle_x | ||
@middle_x ||= left + radius_x | ||
end | ||
|
||
def middle_y | ||
@middle_y ||= top + radius_y | ||
end | ||
|
||
def oval_axis_fraction(axis, input, difference = 0) | ||
(((input - send("middle_#{axis}"))**2).to_f / ((send("radius_#{axis}") - difference)**2)) | ||
end | ||
|
||
def inner_oval_axis_fraction(axis, input) | ||
oval_axis_fraction(axis, input, inner_oval_difference) | ||
end | ||
|
||
def inside_oval?(x, y) | ||
# https://math.stackexchange.com/questions/76457/check-if-a-point-is-within-an-ellipse | ||
# (x - h)**2 (y - k)**2 | ||
# ------- + ------- <= 1 | ||
# Rx ** 2 Ry ** 2 | ||
(oval_axis_fraction(:x, x) + oval_axis_fraction(:y, y)) <= 1 | ||
end | ||
|
||
def inside_inner_oval?(x, y) | ||
x_side = inner_oval_axis_fraction(:x, x) | ||
y_side = inner_oval_axis_fraction(:y, y) | ||
x_side + y_side <= 1 | ||
end | ||
|
||
def normalize_angle(input_angle) | ||
# This fixes angles > 6.283185 and < 0 | ||
input_angle % (Math::PI * 2) | ||
end | ||
|
||
def adjust_angle(input_angle) | ||
# Must pad angle, since angles in standard formulas start at different location than in shoes | ||
adjusted_angle = input_angle + 1.5708 | ||
|
||
# Must make angle 0..6.28318 | ||
normalize_angle(adjusted_angle) | ||
end | ||
|
||
def y_adjust_negative?(input_angle) | ||
((input_angle >= 0) && (input_angle <= 1.5708)) || ((input_angle >= 4.71239) && (input_angle <= 6.28319)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could probably benefit from some constants for these values |
||
end | ||
|
||
def x_adjust_positive?(input_angle) | ||
(input_angle >= 0) && (input_angle <= 3.14159) | ||
end | ||
|
||
def y_result_adjustment(input_angle, y_result) | ||
if y_adjust_negative?(input_angle) | ||
middle_y - y_result | ||
else | ||
middle_y + y_result | ||
end | ||
end | ||
|
||
def x_result_adjustment(input_angle, x_result) | ||
if x_adjust_positive?(input_angle) | ||
middle_x + x_result | ||
else | ||
middle_x - x_result | ||
end | ||
end | ||
|
||
def generate_coordinates(input_angle, x_result, y_result) | ||
x_result = x_result_adjustment(input_angle, x_result).round(3) | ||
y_result = y_result_adjustment(input_angle, y_result).round(3) | ||
|
||
{ | ||
x_value: x_result, | ||
y_value: y_result | ||
} | ||
end | ||
|
||
def tangent_squared(input_angle) | ||
tan(input_angle)**2 | ||
end | ||
|
||
def angle_base_coords(given_angle) | ||
# https://math.stackexchange.com/questions/22064/calculating-a-point-that-lies-on-an-ellipse-given-an-angle | ||
# The above link was used in creating this method...but this implementation varies due to nature of coordinates in shoes | ||
modded_angle = adjust_angle(given_angle) | ||
top_of_equation = (radius_x * radius_y) | ||
|
||
x_result = top_of_equation / (((radius_y**2) + ((radius_x**2) / tangent_squared(modded_angle)))**0.5) | ||
y_result = top_of_equation / (((radius_x**2) + ((radius_y**2) * tangent_squared(modded_angle)))**0.5) | ||
|
||
generate_coordinates(modded_angle, x_result, y_result) | ||
end | ||
|
||
def angle1_coordinates | ||
@angle1_coordinates ||= angle_base_coords(angle1) | ||
end | ||
|
||
def angle2_coordinates | ||
@angle2_coordinates ||= angle_base_coords(angle2) | ||
end | ||
|
||
def angle1_x | ||
angle1_coordinates[:x_value] | ||
end | ||
|
||
def angle1_y | ||
angle1_coordinates[:y_value] | ||
end | ||
|
||
def angle2_x | ||
angle2_coordinates[:x_value] | ||
end | ||
|
||
def angle2_y | ||
angle2_coordinates[:y_value] | ||
end | ||
|
||
def slope_of_angles | ||
# slope = (y2 - y1) / (x2 - x1) | ||
(angle2_y - angle1_y) / (angle2_x - angle1_x) | ||
end | ||
|
||
def b_value_for_line | ||
# SINCE y = mx + b | ||
# THEN b = y - mx | ||
mx_value = (angle1_x * slope_of_angles) | ||
|
||
if mx_value == Float::INFINITY | ||
angle1_y | ||
else | ||
angle1_y - mx_value | ||
end | ||
end | ||
|
||
def vertical_check(x_input) | ||
# The above/below are | ||
if angle1_x == x_input | ||
:on | ||
elsif angle1_x < x_input | ||
:above | ||
else | ||
:below | ||
end | ||
end | ||
|
||
def normal_above_below_check(mx_value, y_input) | ||
right_side_of_equation = mx_value + b_value_for_line | ||
|
||
if right_side_of_equation == y_input | ||
# If input y is same...input is on the line | ||
:on | ||
elsif right_side_of_equation > y_input | ||
# If input y is more, point is above the line | ||
:above | ||
else | ||
# If input y is less, point is below the line | ||
:below | ||
end | ||
end | ||
|
||
def above_below_on(x_input, y_input) | ||
mx_value = (x_input * slope_of_angles) | ||
|
||
if mx_value.abs > 1_000_000.00 | ||
# If line is straight up and down..compare with x value to an x coordinate | ||
vertical_check(x_input) | ||
else | ||
# If standard slope...find what the y value would be given the input x | ||
normal_above_below_check(mx_value, y_input) | ||
end | ||
end | ||
|
||
def angle1_x_smaller_check(x, y) | ||
above_below_on(x, y) == :above && angle1_x < angle2_x | ||
end | ||
|
||
def angle2_x_smaller_check(x, y) | ||
above_below_on(x, y) == :below && angle1_x > angle2_x | ||
end | ||
|
||
def on_shaded_part?(x, y) | ||
angle1_x_smaller_check(x, y) || angle2_x_smaller_check(x, y) | ||
end | ||
|
||
def standard_arc_bounds_check?(x, y) | ||
# Check if it is in the oval, and then if on correct side of the line between points | ||
inside_oval?(x, y) && on_shaded_part?(x, y) | ||
end | ||
|
||
def inner_oval_difference | ||
@inner_oval_difference ||= calculate_inner_oval_difference | ||
end | ||
|
||
def calculate_inner_oval_difference | ||
[style[:strokewidth].to_f, 3.0].max | ||
end | ||
|
||
def in_bounds?(x, y) | ||
bounds_check = standard_arc_bounds_check?(x, y) | ||
|
||
if bounds_check && !style[:fill] | ||
# If no fill, then it is just the edge and needs a further check | ||
bounds_check = !inside_inner_oval?(x, y) | ||
end | ||
|
||
bounds_check | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love love love the reference!