def disc(r=1, center=(0, 0, 0), normal=(0, 0, 1), type='radial', xaxis=(1, 0, 0)): """ Create a circular disc. The *type* parameter distinguishes between different parametrizations. :param float r: Radius :param array-like center: local origin :param array-like normal: local normal :param string type: The type of parametrization ('radial' or 'square') :param array-like xaxis: direction of sem, i.e. parametric start point v=0 :return: The disc :rtype: Surface """ if type == 'radial': c1 = CurveFactory.circle(r, center=center, normal=normal, xaxis=xaxis) c2 = flip_and_move_plane_geometry(c1 * 0, center, normal) result = edge_curves(c2, c1) result.swap() result.reparam((0, r), (0, 2 * pi)) return result elif type == 'square': w = 1 / sqrt(2) cp = [[-r * w, -r * w, 1], [0, -r, w], [r * w, -r * w, 1], [-r, 0, w], [0, 0, 1], [r, 0, w], [-r * w, r * w, 1], [0, r, w], [r * w, r * w, 1]] basis1 = BSplineBasis(3) basis2 = BSplineBasis(3) result = Surface(basis1, basis2, cp, True) return flip_and_move_plane_geometry(result, center, normal) else: raise ValueError('invalid type argument')
def n_gon(n=5, r=1, center=(0,0,0), normal=(0,0,1)): """ Create a regular polygon of *n* equal sides centered at the origin. :param int n: Number of sides and vertices :param float r: Radius :param array-like center: local origin :param array-like normal: local normal :return: A linear, periodic, 2D curve :rtype: Curve :raises ValueError: If radius is not positive :raises ValueError: If *n* < 3 """ if r <= 0: raise ValueError('radius needs to be positive') if n < 3: raise ValueError('regular polygons need at least 3 sides') cp = [] dt = 2 * pi / n knot = [-1] for i in range(n): cp.append([r * cos(i * dt), r * sin(i * dt)]) knot.append(i) knot += [n, n+1] basis = BSplineBasis(2, knot, 0) result = Curve(basis, cp) return flip_and_move_plane_geometry(result, center, normal)
def n_gon(n=5, r=1, center=(0,0,0), normal=(0,0,1)): """n_gon([n=5], [r=1]) Create a regular polygon of *n* equal sides centered at the origin. :param int n: Number of sides and vertices :param float r: Radius :param point-like center: local origin :param vector-like normal: local normal :return: A linear, periodic, 2D curve :rtype: Curve :raises ValueError: If radius is not positive :raises ValueError: If *n* < 3 """ if r <= 0: raise ValueError('radius needs to be positive') if n < 3: raise ValueError('regular polygons need at least 3 sides') cp = [] dt = 2 * pi / n knot = [-1] for i in range(n): cp.append([r * cos(i * dt), r * sin(i * dt)]) knot.append(i) knot += [n, n+1] basis = BSplineBasis(2, knot, 0) result = Curve(basis, cp) return flip_and_move_plane_geometry(result, center, normal)
def disc(r=1, center=(0,0,0), normal=(0,0,1), type='radial'): """disc([r=1], [type='radial']) Create a circular disc. The *type* parameter distinguishes between different parametrizations. :param float r: Radius :param string type: The type of parametrization ('radial' or 'square') :return: The disc :rtype: Surface """ if type == 'radial': c1 = CurveFactory.circle(r) c2 = c1*0 result = edge_curves(c2, c1) result.swap() result.reparam((0,r), (0,2*pi)) elif type == 'square': w = 1 / sqrt(2) cp = [[-r * w, -r * w, 1], [0, -r, w], [r * w, -r * w, 1], [-r, 0, w], [0, 0, 1], [r, 0, w], [-r * w, r * w, 1], [0, r, w], [r * w, r * w, 1]] basis1 = BSplineBasis(3) basis2 = BSplineBasis(3) result = Surface(basis1, basis2, cp, True) else: raise ValueError('invalid type argument') return flip_and_move_plane_geometry(result, center, normal)
def circle_segment(theta, r=1, center=(0, 0, 0), normal=(0, 0, 1), xaxis=(1, 0, 0)): """ Create a circle segment starting parallel to the rotated x-axis. :param float theta: Angle in radians :param float r: Radius :param array-like center: circle segment center :param array-like normal: normal vector to the plane that contains circle :param array-like xaxis: direction of the parametric start point t=0 :return: A quadratic rational curve :rtype: Curve :raises ValueError: If radius is not positive :raises ValueError: If theta is not in the range *[-2pi, 2pi]* """ # error test input if abs(theta) > 2 * pi: raise ValueError('theta needs to be in range [-2pi,2pi]') if r <= 0: raise ValueError('radius needs to be positive') if theta == 2 * pi: return circle(r, center, normal) # build knot vector knot_spans = int(ceil(abs(theta) / (2 * pi / 3))) knot = [0] for i in range(knot_spans + 1): knot += [i] * 2 knot += [knot_spans] # knot vector [0,0,0,1,1,2,2,..,n,n,n] knot = np.array(knot) / float( knot[-1]) * theta # set parametric space to [0,theta] n = (knot_spans - 1) * 2 + 3 # number of control points needed cp = [] t = 0 # current angle dt = float(theta) / knot_spans / 2 # angle step # build control points for i in range(n): w = 1 - (i % 2) * (1 - cos(dt) ) # weights = 1 and cos(dt) every other i x = r * cos(t) y = r * sin(t) cp += [[x, y, w]] t += dt if theta < 0: cp.reverse() result = Curve(BSplineBasis(3, np.flip(knot, 0)), cp, True) else: result = Curve(BSplineBasis(3, knot), cp, True) result.rotate(rotate_local_x_axis(xaxis, normal)) return flip_and_move_plane_geometry(result, center, normal)
def circle(r=1, center=(0,0,0), normal=(0,0,1), type='p2C0', xaxis=(1,0,0)): """ Create a circle. :param float r: Radius :param array-like center: local origin :param array-like normal: local normal :param string type: The type of parametrization ('p2C0' or 'p4C1') :param array-like xaxis: direction of sem, i.e. parametric start point t=0 :return: A periodic, quadratic rational curve :rtype: Curve :raises ValueError: If radius is not positive """ if r <= 0: raise ValueError('radius needs to be positive') if type == 'p2C0' or type == 'C0p2': w = 1.0 / sqrt(2) controlpoints = [[1, 0, 1], [w, w, w], [0, 1, 1], [-w, w, w], [-1, 0, 1], [-w, -w, w], [0, -1, 1], [w, -w, w]] knot = np.array([-1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]) / 4.0 * 2 * pi result = Curve(BSplineBasis(3, knot, 0), controlpoints, True) elif type.lower() == 'p4c1' or type.lower() == 'c1p4': w = 2*sqrt(2)/3 a = 1.0/2/sqrt(2) b = 1.0/6 * (4*sqrt(2)-1) controlpoints = [[ 1,-a, 1], [ 1, a, 1], [ b, b, w], [ a, 1, 1], [-a, 1, 1], [-b, b, w], [-1, a, 1], [-1,-a, 1], [-b,-b, w], [-a,-1, 1], [ a,-1, 1], [ b,-b, w]] knot = np.array([ -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5]) / 4.0 * 2 * pi result = Curve(BSplineBasis(5, knot, 1), controlpoints, True) else: raise ValueError('Unkown type: %s' %(type)) result *= r result.rotate(rotate_local_x_axis(xaxis, normal)) return flip_and_move_plane_geometry(result, center, normal)
def circle(r=1, center=(0,0,0), normal=(0,0,1), type='p2C0'): """circle([r=1]) Create a circle. :param float r: Radius :param point-like center: local origin :param vector-like normal: local normal :param string type: The type of parametrization ('p2C0' or 'p4C1') :return: A periodic, quadratic rational curve :rtype: Curve :raises ValueError: If radius is not positive """ if r <= 0: raise ValueError('radius needs to be positive') if type == 'p2C0' or type == 'C0p2': w = 1.0 / sqrt(2) controlpoints = [[1, 0, 1], [w, w, w], [0, 1, 1], [-w, w, w], [-1, 0, 1], [-w, -w, w], [0, -1, 1], [w, -w, w]] knot = np.array([-1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]) / 4.0 * 2 * pi result = Curve(BSplineBasis(3, knot, 0), controlpoints, True) elif type.lower() == 'p4c1' or type.lower() == 'c1p4': w = 2*sqrt(2)/3 a = 1.0/2/sqrt(2) b = 1.0/6 * (4*sqrt(2)-1) controlpoints = [[ 1,-a, 1], [ 1, a, 1], [ b, b, w], [ a, 1, 1], [-a, 1, 1], [-b, b, w], [-1, a, 1], [-1,-a, 1], [-b,-b, w], [-a,-1, 1], [ a,-1, 1], [ b,-b, w]] knot = np.array([ -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5]) / 4.0 * 2 * pi result = Curve(BSplineBasis(5, knot, 1), controlpoints, True) else: raise ValueError('Unkown type: %s' %(type)) result *= r return flip_and_move_plane_geometry(result, center, normal)
def sphere(r=1, center=(0, 0, 0), zaxis=(0, 0, 1), xaxis=(1, 0, 0)): """ Create a spherical shell. :param float r: Radius :param array-like center: Local origin of the sphere :param array-like zaxis: direction of the north/south pole of the parametrization :param array-like xaxis: direction of the longitudal sem :return: The spherical shell :rtype: Surface """ circle = CurveFactory.circle_segment(pi, r) circle.rotate(-pi / 2) circle.rotate(pi / 2, (1, 0, 0)) # flip up into xz-plane result = revolve(circle) result.rotate(rotate_local_x_axis(xaxis, zaxis)) return flip_and_move_plane_geometry(result, center, zaxis)
def ellipse(r1=1, r2=1, center=(0,0,0), normal=(0,0,1), type='p2C0', xaxis=(1,0,0)): """ Create an ellipse :param float r1: Radius along xaxis :param float r2: Radius orthogonal to xaxis :param array-like center: local origin :param array-like normal: local normal :param string type: The type of parametrization ('p2C0' or 'p4C1') :param array-like xaxis: direction of sem, i.e. parametric start point t=0 :return: A periodic, quadratic rational curve :rtype: Curve :raises ValueError: If radius is not positive """ result = circle(type=type) result *= [r1,r2,1] result.rotate(rotate_local_x_axis(xaxis, normal)) return flip_and_move_plane_geometry(result, center, normal)
def circle_segment(theta, r=1, center=(0,0,0), normal=(0,0,1)): """circle_segment(theta, [r=1]) Create a circle segment starting paralell to the rotated x-axis. :param float theta: Angle in radians :param float r: Radius :return: A quadratic rational curve :rtype: Curve :raises ValueError: If radiusis not positive :raises ValueError: If theta is not in the range *[-2pi, 2pi]* """ # error test input if abs(theta) > 2 * pi: raise ValueError('theta needs to be in range [-2pi,2pi]') if r <= 0: raise ValueError('radius needs to be positive') if theta == 2*pi: return circle(r, center, normal) # build knot vector knot_spans = int(ceil(theta / (2 * pi / 3))) knot = [0] for i in range(knot_spans + 1): knot += [i] * 2 knot += [knot_spans] # knot vector [0,0,0,1,1,2,2,..,n,n,n] knot = np.array(knot) / float(knot[-1]) * theta # set parametic space to [0,theta] n = (knot_spans - 1) * 2 + 3 # number of control points needed cp = [] t = 0 # current angle dt = float(theta) / knot_spans / 2 # angle step # build control points for i in range(n): w = 1 - (i % 2) * (1 - cos(dt)) # weights = 1 and cos(dt) every other i x = r * cos(t) y = r * sin(t) cp += [[x, y, w]] t += dt result = Curve(BSplineBasis(3, knot), cp, True) return flip_and_move_plane_geometry(result, center, normal)
def torus(minor_r=1, major_r=3, center=(0,0,0), normal=(0,0,1), xaxis=(1,0,0)): """ Create a torus (doughnut) by revolving a circle of size *minor_r* around the *z* axis with radius *major_r*. :param float minor_r: The thickness of the torus (radius in the *xz* plane) :param float major_r: The size of the torus (radius in the *xy* plane) :param array-like center: Local origin of the torus :param array-like normal: Local origin of the torus :param array-like center: Local origin of the torus :return: A periodic torus :rtype: Surface """ circle = CurveFactory.circle(minor_r) circle.rotate(pi / 2, (1, 0, 0)) # flip up into xz-plane circle.translate((major_r, 0, 0)) # move into position to spin around z-axis result = revolve(circle) result.rotate(rotate_local_x_axis(xaxis, normal)) return flip_and_move_plane_geometry(result, center, normal)
def plane(self): dim = int( self.read_next_non_whitespace().strip()) center = np.array(next(self.fstream).split(), dtype=float) normal = np.array(next(self.fstream).split(), dtype=float) x_axis = np.array(next(self.fstream).split(), dtype=float) finite = next(self.fstream).strip() != '0' if finite: param_u= np.array(next(self.fstream).split(), dtype=float) param_v= np.array(next(self.fstream).split(), dtype=float) else: param_u= [-state.unlimited, +state.unlimited] param_v= [-state.unlimited, +state.unlimited] swap = next(self.fstream).strip() != '0' result = Surface() * [param_u[1]-param_u[0], param_v[1]-param_v[0]] + [param_u[0],param_v[0]] result.rotate(rotate_local_x_axis(x_axis, normal)) result = flip_and_move_plane_geometry(result,center,normal) result.reparam(param_u, param_v) if(swap): result.swap() return result