def __init__(self, lines, verbose=True): self._lines = [] self.verbose = verbose if isinstance(lines, Link): self.lines = [Knot(line) for line in lines.lines] else: lines = [Knot(line) for line in lines] self.lines = lines self._crossings = None self._gauss_code = {} self._recent_octree = None
def k4_1(num_points=100): '''Returns a particular figure eight knot conformation.''' data = n.zeros((num_points, 3), dtype=n.float64) ts = n.linspace(0, 2 * n.pi, num_points) data[:, 0] = (2 + n.cos(2 * ts)) * n.cos(3 * ts) data[:, 1] = (2 + n.cos(2 * ts)) * n.sin(3 * ts) data[:, 2] = n.sin(4 * ts) return Knot(data)
def unknot(num_points=100): '''Returns a simple circle.''' data = n.zeros((num_points, 3), dtype=n.float64) ts = n.linspace(0, 2 * n.pi, num_points) data[:, 0] = 3 * n.sin(ts) data[:, 1] = 3 * n.cos(ts) data[:, 2] = n.sin(3 * ts) return Knot(data)
def octree_simplify(self, runs=1, plot=False, rotate=True, obey_knotting=False, **kwargs): ''' Simplifies the curves via the octree reduction of :module:`pyknotid.simplify.octree`. Parameters ---------- runs : int The number of times to run the octree simplification. Defaults to 1. plot : bool Whether to plot the curve after each run. Defaults to False. rotate : bool Whether to rotate the space curve before each run. Defaults to True as this can make things much faster. obey_knotting : bool Whether to not let the line pass through itself. Defaults to False - knotting of individual components will be ignored! This is *much* faster than the alternative. kwargs are passed to the :class:`pyknotid.simplify.octree.OctreeCell` constructor. ''' from ..simplify.octree import OctreeCell, remove_nearby_points for line in self.lines: line.points = remove_nearby_points(line.points) for i in range(runs): if n.sum([len(knot.points) for knot in self.lines]) > 30: vprint( '\rRun {} of {}, {} points remain'.format( i, runs, len(self)), False, self.verbose) if rotate: rot_mat = get_rotation_matrix(n.random.random(3)) for line in self.lines: line._apply_matrix(rot_mat) oc = OctreeCell.from_lines([line.points for line in self.lines], **kwargs) oc.simplify(obey_knotting) self._recent_octree = oc self.lines = [Knot(line) for line in oc.get_lines()] for line in self.lines: line.points = remove_nearby_points(line.points) if rotate: for line in self.lines: line._apply_matrix(rot_mat.T) if plot: self.plot() vprint('\nReduced to {} points'.format(len(self)))
def lissajous(nx=3, ny=2, nz=7, px=0.7, py=0.2, pz=0., num_points=100): '''Returns a `Lissajous knot <https://en.wikipedia.org/wiki/Lissajous_knot>`__ with the given parameters.''' data = n.zeros((num_points, 3), dtype=n.float64) ts = n.linspace(0, 2 * n.pi, num_points) data[:, 0] = n.cos(nx * ts + px) data[:, 1] = n.cos(ny * ts + py) data[:, 2] = n.cos(nz * ts + pz) return Knot(data)
def knot_from_text(text): points = [] for line in text.split('\n'): values = line.split(' ') if len(values) == 1 and len(values[0]) == 0: continue if len(values) != 3: raise ValueError('Invalid text passed.') points.append([float(v) for v in values]) k = Knot(points, verbose=False) return k
def torus_knot(p=3, q=4, num=100): ''' Returns points in the p, q torus knot. If p and q are not coprime, returns only the first component. Parameters ---------- p : int The number of times the knot winds around the outside of the torus. Defaults to 3. q : int The number of times the knot passes through the hole in the centre of the torus. Defaults to 4. num_points : int The number of points in the returned piecewise linear curve. If there are multiple curves (i.e. a torus link), this is the number of points in *each* curve. Defaults to 100. ''' return Knot( TorusKnot(p, q, num, minor_radius=1.5, major_radius=3).first_component)
def from_periodic_lines(cls, lines, shape, perturb=True): '''Returns a :class:`Link` instance in which the lines have been unwrapped through the periodic boundaries. Parameters ---------- line : list A list of the Nx3 vectors of points in the lines shape : array-like The x, y, z distances of the periodic boundary perturb : bool If True, translates and rotates the knot to avoid any lattice problems. ''' shape = ensure_shape_tuple(shape) lines = [ Knot.from_periodic_line(line, shape, perturb=False) for line in lines ] link = cls(lines) if perturb: link.translate(n.array([0.00123, 0.00231, 0.00321])) link.rotate() return link