pythonshapestrigonometry

Get x and y radius of a hexagon no matter the angle


I created a hexagon blur that gives this kind of results:

hexagon blur

To make the code a bit cleaner, I created a hexagon class. I'm now implementing different methods inside.

My constructor look to this for now:

def __init__(self, radius, center_x, center_y, angle=0):
        self._dmin = np.sqrt(3)/2

        self._radius = radius
        self._radius_min = radius * self.dmin
        self._center_x = center_x
        self._center_y = center_y

        self._angle = angle  # Angle in degrees
        self._radian = np.radians(self.angle)

        self._period = 60

I stuck on the methods radiusX and radiusY. This methods should give in output the distance from the center to the border based on the current hexagon center. For radiusX with a y at 0 and radiusY with a x at 0. enter image description here

I tried different implementations but the more accurate one I got until now is:

def radiusX(self) -> float:
        return self.radius_min + Trigonometry.one2Zero2One(x=self.angle%self.period, period=self.period) * (self.radius - self.radius_min)

    def radiusY(self) -> float:
        return self.radius_min + Trigonometry.zero2One2Zero(x=self.angle%self.period, period=self.period) * (self.radius - self.radius_min)

The methods one2Zero2One() and zero2One2Zero() are implemented like this:

    @staticmethod
    def one2Zero2One(x, period):
        return 0.5 + 0.5 * np.cos(x * np.pi / (period / 2))

    @staticmethod
    def zero2One2Zero(x, period):
        return 0.5 + 0.5 * np.sin(x * np.pi / (period / 2) - 1.58)

They allow you to obtain a value on a bell between 0 and 1. zero2One2Zero look to this:

zero2One2Zero

In my class, a hexagon with an angle of 0 is in this direction:

direction

I know that my two methods are not good because when I visualise the results with plotly, I directly see that the radius doesn't follow the one2Zero2One and zero2One2Zero curves. In the examples below, above and on the right is have a green point which indicate the end of the x and y radius:

angle1

angle2

angle3

angle4

angle5

angle6

angle7

This graphics are obtained with:

h = Hexagon(radius=0.5, center_x=0.5, center_y=0.5, angle=j)
        fig = go.Figure()
        inside = {'x':[], 'y':[]}
        outside = {'x':[], 'y':[]}
        radius = {'x':[h.center_x + h.radiusX(), h.center_y], 'y':[h.center_y, h.center_y + h.radiusY()]}
        print(h.radiusX())
        for i in range(int(10e3)):
            # print(i,'/',int(10e3))
            x, y = random(), random()
            if h.isPointInside(x, y):
                inside['x'].append(x)
                inside['y'].append(y)
            else:
                outside['x'].append(x)
                outside['y'].append(y)

        fig.add_trace(go.Scatter(x=inside['x'], y=inside['y'], mode='markers', name='Inside'))
        fig.add_trace(go.Scatter(x=outside['x'], y=outside['y'], mode='markers', name='Outside'))
        fig.add_trace(go.Scatter(x=radius['x'], y=radius['y'], mode='markers', name='radius', marker={'size':10}))
        fig.show()

What is the correct equation for getting the radiusX and radiusY based on the current hexagon angle?


Solution

  • As far as your code goes, you don't need to use anything besides core Python for the geometric computations.

    The math module provides the trigonometric and transcendental functions you need:

    from math import sin, cos, sqrt, degrees, radians, pi
    

    No need for NumPy:

    The only use for np variants of radians, degrees, sqrt, etc. is to have automatic broadcasting across NumPy arrays. Since you're dealing with scalars, bringing NumPy into the picture only muddies the water. Stick to core Python where possible - it makes the code easier to understand.

    NumPy is useful for image manipulations, since it'll be faster than even fairly streamlined Python code. Nevertheless, the specializing compiler in Python 3.13 can already make NumPy unnecessary for some tasks :)

    enter image description here

    Suppose we have an n-polygon inscribed into a circle of radius r.

    Then:

    (1) α = 360°/n

    From basic trigonometry:

    (2) h/r = cos(γ) = cos(α/2), thus h = r cos(α/2)

    (3) h/dx = cos(β), thus dx = h/cos(β)

    Substituting (2) into (3), we get

    (4) dx = r cos(α/2) / cos(β)

    Then we substitute (1) into (4), and finally

    (5) dx = r cos(180°/n) / cos(β)

    You can work out dy similarly.

    To investigate such geometric problems, GeoGebra works well. That's what I used to make the illustration above. That's what you should use to make properly labeled illustrations for your question. Help us help you!

    Note: It is not possible to select overlapping objects well in GeoGebra - only the "first one" gets selected when you click on overlapping objects. To help selecting a particular object when they overlap (e.g. a short segment overlapping a long segment), switch from "Tools" to "Algebra" and you'll get a list of objects that you can select within the list.

    enter image description here