Source code for geometry

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""2D geometry objects.

:Date: 2019-03-21

.. module:: geometry
  :platform: *nix, Windows
  :synopsis: Geometry objects.
   
.. moduleauthor:: Daniel Weschke <daniel.weschke@directbox.de>
"""
import math
import numpy as np


[docs]def translate(vec, *pts): """Translate a point or polygon by a given vector. :param vec: translation vector :type vec: tuple :param `*pts`: points to translate :returns: (point_x, point_y) or (point1, point2, ...) :rtype: tuple """ vx, vy = vec return tuple([(x+vx, y+vy) for (x, y) in pts])
[docs]def rotate(origin, angle, *pts, **kwargs): """Rotate a point or polygon counterclockwise by a given angle around a given origin. The angle should be given in radians. :param origin: the center of rotation :type origin: tuple :param angle: the rotation angle :type angle: int or float :param `*pts`: points to rotate :param `**kwargs`: options :returns: (point_x, point_y) or (point1, point2, ...) :rtype: tuple """ ox, oy = origin # add first point to the end if kwargs is not None and "closed" in kwargs and kwargs["closed"] is True: pts += (pts[0],) result = tuple([(ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy), oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy)) for (px, py) in pts]) if len(pts) == 1: return result[0][0], result[0][1] return result
[docs]def rotate_deg(origin, angle, *pts, **kwargs): """Rotate a point or polygon counterclockwise by a given angle around a given origin. The angle should be given in degrees. :param origin: the center of rotation :type origin: tuple :param angle: the rotation angle :type angle: int or float :param `*pts`: points to rotate :param `**kwargs`: options :returns: (point_x, point_y) or (point1, point2, ...) :rtype: tuple .. seealso:: :meth:`rotate` """ return rotate(origin, angle*math.pi/180, *pts, **kwargs)
[docs]def rectangle(width, height): """\ :param width: the width of the rectangle :type width: int or float :param height: the height of the rectangle :type height: int or float :returns: (point1, point2, point3, point4) :rtype: tuple """ pt1 = (-width/2, -height/2) pt2 = (width/2, -height/2) pt3 = (width/2, height/2) pt4 = (-width/2, height/2) return pt1, pt2, pt3, pt4, pt1
[docs]def square(width): """\ :param width: the edge size of the square :type width: int or float :returns: (point1, point2, point3, point4) :rtype: tuple .. seealso:: :meth:`rectangle` """ return rectangle(width, width)
# # matplotlib format, return lists for x and y #
[docs]def points(*pts): """\ :param `*pts`: points to rearrange :returns: ((point1_x, point2_x), (point1_y, point2_y), ...) :rtype: tuple """ return zip(*pts)
[docs]def line(point1, point2, samples=2): """\ .. math:: y = \\frac{y_2-y_1}{x_2-x_1}(x-x_1) + y_1 :param point1: one end point :type point1: tuple :param point2: other end point :type point2: tuple :param samples: number of sampling points :type samples: int :returns: ((point1_x, point2_x), (points1_y, point2_y)) or ([sample_point1_x, sample_point2_x, ...], [sample_points1_y, sample_point2_y, ...]) :rtype: tuple """ p1x, p1y = point1 p2x, p2y = point2 denominator = (p1x - p2x) if samples > 2 and denominator > 0: x = np.linspace(p1x, p2x) a = (p1y - p2y) / denominator b = (p1x*p2y - p2x*p1y) / denominator y = a*x + b return x, y return (p1x, p2x), (p1y, p2y) # matplotlib format
[docs]def cubic(point1, angle1, point2, angle2, samples=50): """\ :param point1: one end point :type point1: tuple :param angle1: the slope at the one end point :type angle1: int or float :param point2: other end point :type point2: tuple :param angle2: the slope at the other end point :type angle2: int or float :param samples: number of sampling points :type samples: int :returns: ([sample_point1_x, sample_point2_x, ...], [sample_points1_y, sample_point2_y, ...]) :rtype: tuple """ p1x, p1y = point1 p2x, p2y = point2 x = np.linspace(p1x, p2x, num=samples) p1ys = math.tan(angle1) p2ys = math.tan(angle2) a = (p1x*p1ys + p1x*p2ys - p2x*p1ys - p2x*p2ys - 2*p1y + 2*p2y)/(p1x**3 - 3*p1x**2*p2x + 3*p1x*p2x**2 - p2x**3) b = (- p1x**2*p1ys - 2*p1x**2*p2ys - p1x*p2x*p1ys + p1x*p2x*p2ys + 3*p1x*p1y - 3*p1x*p2y + 2*p2x**2*p1ys + p2x**2*p2ys + 3*p2x*p1y - 3*p2x*p2y)/(p1x**3 - 3*p1x**2*p2x + 3*p1x*p2x**2 - p2x**3) c = (p1x**3*p2ys + 2*p1x**2*p2x*p1ys + p1x**2*p2x*p2ys - p1x*p2x**2*p1ys - 2*p1x*p2x**2*p2ys - 6*p1x*p2x*p1y + 6*p1x*p2x*p2y - p2x**3*p1ys)/(p1x**3 - 3*p1x**2*p2x + 3*p1x*p2x**2 - p2x**3) d = (- p1x**3*p2x*p2ys + p1x**3*p2y - p1x**2*p2x**2*p1ys + p1x**2*p2x**2*p2ys - 3*p1x**2*p2x*p2y + p1x*p2x**3*p1ys + 3*p1x*p2x**2*p1y - p2x**3*p1y)/(p1x**3 - 3*p1x**2*p2x + 3*p1x*p2x**2 - p2x**3) y = a*x**3 + b*x**2 + c*x + d return x, y
[docs]def cubic_deg(point1, angle1, point2, angle2): """\ :param point1: one end point :type point1: tuple :param angle1: the slope at the one end point :type angle1: int or float :param point2: other end point :type point2: tuple :param angle2: the slope at the other end point :type angle2: int or float :returns: ([sample_point1_x, sample_point2_x, ...], [sample_points1_y, sample_point2_y, ...]) :rtype: tuple .. seealso:: :meth:`cubic` """ return cubic(point1, angle1 * math.pi/180, point2, angle2 * math.pi/180)