Refactored algorithm and documented

The new algorithm places circles with more dependencies so that the spacing
between kitty corner and circles on the same line are the same.
This commit is contained in:
Jesse Millwood 2023-09-12 19:56:18 -04:00
parent 28f126df71
commit 13f513e4b8

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inkex import inkex
import math
class HoneyCombExtension(inkex.EffectExtension): class HoneyCombExtension(inkex.EffectExtension):
def add_arguments(self, pars): def add_arguments(self, pars):
@ -38,36 +39,84 @@ class HoneyCombExtension(inkex.EffectExtension):
if target.get("r"): if target.get("r"):
# Selection is a circle # Selection is a circle
target_rad = float(target.get("r"))
target_dia = 2 * float(target_rad)
target_style = target.get("style")
difference = bounding_box_w - (target_dia * self.options.count_x) # Draw Honeycomb circles in a bounding box
target_spacing = difference/(self.options.count_x) # +------ ---------------------------------------------------+
# | * * |-s1-| * * |
# | * * | | * * |
# | * (x1,y1) *| |* (x2,y2) * |
# | * |\ * * * |
# | * | \ * * * |
# | *| *\ c * * |
# | | \ * * |
# | a| * * |
# | | * (x3,y3) * |
# | |___*____ * |
# | b * * |
# | * * |
# | |
# +----------------------------------------------------------+
# Known values:
# =============
# Circle centers known: (x1,y1) and (x2,y2)
# Radius of circles known: r1, r2, r3 and r1=r2=r3
# Therefore, spacing, s1 is known
# Spacing Between circle 1 and 2: s1 = x2-x1-2r
#
# Calculate coordinages for circle 3:
# ===================================
# Triangle to find coordinates of circle 3:
# |\
# | \
# a| \c
# | \
# |____\
# b
# a^2+b^2=c^2
# a = (c^2-b^2)^1/2
# b = (x2-x1)/2
# c = r1+r3+s1
# = 2r1+(x1-x2-2r)
# = x1-x2
# a = ((x2-x1)^2 -((x2-x1)/2)^2)^1/2
#
# x3 = x1 + ((x2-x1)/2)
# y3 = y2 - sqrt((x2-x1)^2 - ((x2-x1)/2)^2)
circle_r = float(target.get("r"))
circle_d = 2 * circle_r
circle_style = target.get("style")
shift_row = True # Calculate spacing between circles in a row to fit a
# given bounding box
left_over = bounding_box_w - (circle_d * self.options.count_x)
spacing = left_over/(self.options.count_x)
circ_center_diff = spacing + (2 * circle_r)
shift_row = False
y_coord_last = 0
for y_cnt in range(0, self.options.count_y): for y_cnt in range(0, self.options.count_y):
y_coord = (bounding_box_y + target_rad) if y_cnt == 0:
y_coord += y_cnt * target_dia y_coord = bounding_box_y + circle_r
if y_cnt % 2 != 0: else:
shift_row = True y_coord = y_coord_last + math.sqrt(pow(circ_center_diff,2)-pow(circ_center_diff/2,2))
if shift_row:
num_x = self.options.count_x + 1 num_x = self.options.count_x + 1
else: else:
shift_row = False
num_x = self.options.count_x num_x = self.options.count_x
for x_cnt in range(0, num_x): for x_cnt in range(0, num_x):
x_coord = bounding_box_x + target_rad if shift_row is True:
x_coord += x_cnt * (target_spacing + target_dia) x_coord_int = bounding_box_x
if shift_row:
x_coord -= target_rad
else: else:
x_coord += target_spacing / 2 x_coord_int = bounding_box_x + (spacing/2) + circle_r
x_coord = x_coord_int + (x_cnt * circ_center_diff)
circ = inkex.Circle(attrib={"cx": f"{x_coord}", circ = inkex.Circle(attrib={"cx": f"{x_coord}",
"cy": f"{y_coord}", "cy": f"{y_coord}",
"r": f"{target_rad}", "r": f"{circle_r}",
"style": target_style}) "style": circle_style})
layer = self.svg.get_current_layer() layer = self.svg.get_current_layer()
layer.append(circ) layer.append(circ)
y_coord_last = y_coord
shift_row ^= True
elif target.get("rx"): elif target.get("rx"):
# Selection is an elipse # Selection is an elipse