Skip to content

Commit

Permalink
Merge pull request #643 from jdegenstein/hexloc_majradius
Browse files Browse the repository at this point in the history
Add major_radius bool to HexLocations and rename apothem parameter to radius
  • Loading branch information
jdegenstein authored Jun 20, 2024
2 parents 35a33f8 + f383470 commit 29ad538
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 12 deletions.
2 changes: 1 addition & 1 deletion examples/heat_exchanger.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
tube_locations = [
l
for l in HexLocations(
apothem=(tube_diameter + tube_spacing) / 2,
radius=(tube_diameter + tube_spacing) / 2,
x_count=exchanger_diameter // tube_diameter,
y_count=exchanger_diameter // tube_diameter,
)
Expand Down
2 changes: 1 addition & 1 deletion examples/heat_exchanger_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
tube_locations = [
l
for l in HexLocations(
apothem=(tube_diameter + tube_spacing) / 2,
radius=(tube_diameter + tube_spacing) / 2,
x_count=exchanger_diameter // tube_diameter,
y_count=exchanger_diameter // tube_diameter,
)
Expand Down
39 changes: 29 additions & 10 deletions src/build123d/build_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
import functools
from abc import ABC, abstractmethod
from itertools import product
from math import sqrt
from math import sqrt, cos, pi
from typing import Any, Callable, Iterable, Optional, Union, TypeVar
from typing_extensions import Self, ParamSpec, Concatenate

Expand Down Expand Up @@ -860,20 +860,30 @@ class HexLocations(LocationList):
"""Location Context: Hex Array
Creates a context of hexagon array of locations for Part or Sketch. When creating
hex locations for an array of circles, set `apothem` to the radius of the circle
hex locations for an array of circles, set `radius` to the radius of the circle
plus one half the spacing between the circles.
Args:
apothem (float): radius of the inscribed circle
xCount (int): number of points ( > 0 )
yCount (int): number of points ( > 0 )
radius (float): distance from origin to vertices (major), or
optionally from the origin to side (minor or apothem)
with major_radius = False
x_count (int): number of points ( > 0 )
y_count (int): number of points ( > 0 )
major_radius (bool): If True the radius is the major radius, else the
radius is the minor radius (also known as inscribed radius).
Defaults to False.
align (Union[Align, tuple[Align, Align]], optional): align min, center, or max of object.
Defaults to (Align.CENTER, Align.CENTER).
Attributes:
apothem (float): radius of the inscribed circle
xCount (int): number of points ( > 0 )
yCount (int): number of points ( > 0 )
radius (float): distance from origin to vertices (major), or
optionally from the origin to side (minor or apothem)
with major_radius = False
apothem (float): radius of the inscribed circle, also known as minor radius
x_count (int): number of points ( > 0 )
y_count (int): number of points ( > 0 )
major_radius (bool): If True the radius is the major radius, else the
radius is the minor radius (also known as inscribed radius).
align (Union[Align, tuple[Align, Align]]): align min, center, or max of object.
diagonal (float): major radius
local_locations (list{Location}): locations relative to workplane
Expand All @@ -884,23 +894,32 @@ class HexLocations(LocationList):

def __init__(
self,
apothem: float,
radius: float,
x_count: int,
y_count: int,
major_radius: bool = False,
align: Union[Align, tuple[Align, Align]] = (Align.CENTER, Align.CENTER),
):
# pylint: disable=too-many-locals

diagonal = 4 * apothem / sqrt(3)
if major_radius:
diagonal = 2 * radius
apothem = radius * cos(pi / 6)
else:
diagonal = 4 * radius / sqrt(3)
apothem = radius

x_spacing = 3 * diagonal / 4
y_spacing = diagonal * sqrt(3) / 2
if x_spacing <= 0 or y_spacing <= 0 or x_count < 1 or y_count < 1:
raise ValueError("Spacing and count must be > 0 ")

self.radius = radius
self.apothem = apothem
self.diagonal = diagonal
self.x_count = x_count
self.y_count = y_count
self.major_radius = major_radius
self.align = tuplify(align, 2)

# Generate the raw coordinates relative to bottom left point
Expand Down
10 changes: 10 additions & 0 deletions tests/test_build_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,16 @@ def test_hex_no_centering(self):
for position in positions:
self.assertTrue(position.X <= 0 and position.Y <= 0)

def test_hex_major_radius(self):
hex = RegularPolygon(1, 6)
with BuildSketch() as s:
with HexLocations(1, 3, 3, major_radius=True) as hloc:
add(hex)
self.assertAlmostEqual(s.sketch.face().area, hex.area * 9, 7)
self.assertAlmostEqual(hloc.radius, 1, 7)
self.assertAlmostEqual(hloc.diagonal, 2, 7)
self.assertAlmostEqual(hloc.apothem, 3**0.5 / 2, 7)

def test_centering(self):
with BuildSketch():
with GridLocations(4, 4, 2, 2, align=(Align.CENTER, Align.CENTER)) as l:
Expand Down

0 comments on commit 29ad538

Please sign in to comment.