def star(cls, peak_count, radius1, radius2, center=(0, 0), angle=0): """Create a radial pointed star polygon with the specified number of peaks. :param peak_count: The number of peaks. The resulting polygon will have twice this number of vertices. Must be >= 2. :type peak_count: int :param radius1: The peak or valley vertex radius. A vertex is aligned on ``angle`` with this radius. :type radius1: float :param radius2: The alternating vertex radius. :type radius2: float :param center: The center point of the polygon. If omitted, the polygon will be centered on the origin. :type center: Vec2 :param angle: The starting angle for the vertices, in degrees. :type angle: float """ if peak_count < 2: raise ValueError( "star polygon must have a minimum of 2 peaks") cx, cy = center angle_step = 180.0 / peak_count verts = [] for i in range(peak_count): x, y = cos_sin_deg(angle) verts.append((x * radius1 + cx, y * radius1 + cy)) angle += angle_step x, y = cos_sin_deg(angle) verts.append((x * radius2 + cx, y * radius2 + cy)) angle += angle_step is_simple = (radius1 > 0.0) == (radius2 > 0.0) poly = cls(verts, is_convex=(radius1 == radius2), is_simple=is_simple or None) if is_simple: poly._centroid = planar.Vec2(*center) poly._max_r = max_r = max(abs(radius1), abs(radius2)) poly._max_r2 = max_r * max_r if (radius1 >= 0.0) == (radius2 >= 0.0): if not poly.is_convex: poly._min_r = min_r = min(abs(radius1), abs(radius2)) poly._min_r2 = min_r * min_r else: poly._min_r = min_r = ( (poly[0] + poly[1]) * 0.5 - center).length poly._min_r2 = min_r * min_r if radius1 > 0.0 and radius2 > 0.0: poly._dupe_verts = False return poly
def star(cls, peak_count, radius1, radius2, center=(0, 0), angle=0): """Create a radial pointed star polygon with the specified number of peaks. :param peak_count: The number of peaks. The resulting polygon will have twice this number of vertices. Must be >= 2. :type peak_count: int :param radius1: The peak or valley vertex radius. A vertex is aligned on ``angle`` with this radius. :type radius1: float :param radius2: The alternating vertex radius. :type radius2: float :param center: The center point of the polygon. If omitted, the polygon will be centered on the origin. :type center: Vec2 :param angle: The starting angle for the vertices, in degrees. :type angle: float """ if peak_count < 2: raise ValueError("star polygon must have a minimum of 2 peaks") cx, cy = center angle_step = 180.0 / peak_count verts = [] for i in range(peak_count): x, y = cos_sin_deg(angle) verts.append((x * radius1 + cx, y * radius1 + cy)) angle += angle_step x, y = cos_sin_deg(angle) verts.append((x * radius2 + cx, y * radius2 + cy)) angle += angle_step is_simple = (radius1 > 0.0) == (radius2 > 0.0) poly = cls(verts, is_convex=(radius1 == radius2), is_simple=is_simple or None) if is_simple: poly._centroid = planar.Vec2(*center) poly._max_r = max_r = max(abs(radius1), abs(radius2)) poly._max_r2 = max_r * max_r if (radius1 >= 0.0) == (radius2 >= 0.0): if not poly.is_convex: poly._min_r = min_r = min(abs(radius1), abs(radius2)) poly._min_r2 = min_r * min_r else: poly._min_r = min_r = ((poly[0] + poly[1]) * 0.5 - center).length poly._min_r2 = min_r * min_r if radius1 > 0.0 and radius2 > 0.0: poly._dupe_verts = False return poly
def regular(cls, vertex_count, radius, center=(0, 0), angle=0): """Create a regular polygon with the specified number of vertices radius distance from the center point. Regular polygons are always convex. :param vertex_count: The number of vertices in the polygon. Must be >= 3. :type vertex_count: int :param radius: distance from vertices to center point. :type radius: float :param center: The center point of the polygon. If omitted, the polygon will be centered on the origin. :type center: Vec2 :param angle: The starting angle for the vertices, in degrees. :type angle: float """ cx, cy = center angle_step = 360.0 / vertex_count verts = [] for i in range(vertex_count): x, y = cos_sin_deg(angle) verts.append((x * radius + cx, y * radius + cy)) angle += angle_step poly = cls(verts, is_convex=True) poly._centroid = planar.Vec2(*center) poly._max_r = radius poly._max_r2 = radius * radius poly._min_r = min_r = ((poly[0] + poly[1]) * 0.5 - center).length poly._min_r2 = min_r * min_r poly._dupe_verts = False return poly
def rotated(self, angle): """Compute the vector rotated by an angle. :param angle: The angle to rotate by, in degrees. :type angle: float :rtype: Vec2 """ vx, vy = self ca, sa = cos_sin_deg(angle) return tuple.__new__(Vec2, (vx * ca - vy * sa, vx * sa + vy * ca))
def polar(cls, angle, length=1.0): """Create a vector from polar coordinates. :param angle: Vector angle in degrees from the positive x-axis. :type angle: float :param length: The length of the vector. :type length: float :rtype: Vec2 """ x, y = cos_sin_deg(angle) vec = tuple.__new__(cls, (x * length, y * length)) vec.__dict__['length'] = length * 1.0 return vec
def rotation(cls, angle, pivot=None): """Create a rotation transform at the specified angle, optionally about the specified pivot point. :param angle: Rotation angle in degrees :type angle: float :param pivot: Point to rotate about, if omitted the rotation is about the origin. :type pivot: :class:`~planar.Vec2` :rtype: Affine """ ca, sa = cos_sin_deg(angle) if pivot is None: return tuple.__new__(cls, (ca, sa, 0.0, -sa, ca, 0.0, 0.0, 0.0, 1.0)) else: px, py = pivot return tuple.__new__(cls, (ca, sa, px - px * ca + py * sa, -sa, ca, py - px * sa - py * ca, 0.0, 0.0, 1.0))
def rotation(cls, angle, pivot=None): """Create a rotation transform at the specified angle, optionally about the specified pivot point. :param angle: Rotation angle in degrees :type angle: float :param pivot: Point to rotate about, if omitted the rotation is about the origin. :type pivot: :class:`~planar.Vec2` :rtype: Affine """ ca, sa = cos_sin_deg(angle) if pivot is None: return tuple.__new__(cls, (ca, sa, 0.0, -sa, ca, 0.0, 0.0, 0.0, 1.0)) else: px, py = pivot return tuple.__new__(cls, (ca, sa, px - px*ca + py*sa, -sa, ca, py - px*sa - py*ca, 0.0, 0.0, 1.0))