From 9178b6b22389333d19c12bd4d8b253fa9e3aa661 Mon Sep 17 00:00:00 2001 From: meta-androcto Date: Fri, 5 Aug 2016 18:38:21 +1000 Subject: curve extra objects: clean up imports, add surface objects --- add_curve_extra_objects/__init__.py | 33 +- add_curve_extra_objects/add_curve_aceous_galore.py | 9 +- add_curve_extra_objects/add_curve_spirals.py | 71 ++-- add_curve_extra_objects/add_curve_torus_knots.py | 137 ++++--- add_curve_extra_objects/add_surface_plane_cone.py | 451 +++++++++++++++++++++ 5 files changed, 600 insertions(+), 101 deletions(-) create mode 100644 add_curve_extra_objects/add_surface_plane_cone.py (limited to 'add_curve_extra_objects') diff --git a/add_curve_extra_objects/__init__.py b/add_curve_extra_objects/__init__.py index 945a8ac5..ec45c1c1 100644 --- a/add_curve_extra_objects/__init__.py +++ b/add_curve_extra_objects/__init__.py @@ -28,22 +28,26 @@ bl_info = { "warning": "", "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/" "Scripts/Curve/Curve_Objects", - "category": "Add Curve"} + "category": "Add Curve" + } if "bpy" in locals(): - import imp - imp.reload(add_curve_aceous_galore) - imp.reload(add_curve_spirals) - imp.reload(add_curve_torus_knots) + import importlib + importlib.reload(add_curve_aceous_galore) + importlib.reload(add_curve_spirals) + importlib.reload(add_curve_torus_knots) + importlib.reload(add_surface_plane_cone) else: from . import add_curve_aceous_galore from . import add_curve_spirals from . import add_curve_torus_knots + from . import add_surface_plane_cone import bpy +from bpy.types import Menu -class INFO_MT_curve_extras_add(bpy.types.Menu): +class INFO_MT_curve_extras_add(Menu): # Define the "Extras" menu bl_idname = "curve_extra_objects_add" bl_label = "Extra Objects" @@ -57,8 +61,10 @@ class INFO_MT_curve_extras_add(bpy.types.Menu): text="Spirals") layout.operator("curve.torus_knot_plus", text="Torus Knot Plus") -# Define "Extras" menu + +# Define "Extras" menus def menu_func(self, context): + self.layout.separator() self.layout.operator("mesh.curveaceous_galore", text="Curve Profiles") self.layout.operator("curve.torus_knot_plus", @@ -66,17 +72,30 @@ def menu_func(self, context): self.layout.operator("curve.spirals", text="Spirals") +def menu_surface(self, context): + layout = self.layout + self.layout.separator() + self.layout.operator("object.add_surface_wedge", text="Wedge", icon="MOD_CURVE") + self.layout.operator("object.add_surface_cone", text="Cone", icon="MOD_CURVE") + self.layout.operator("object.add_surface_star", text="Star", icon="MOD_CURVE") + self.layout.operator("object.add_surface_plane", text="Plane", icon="MOD_CURVE") + self.layout.operator("curve.smooth_x_times", text="Special Smooth", icon="MOD_CURVE") + def register(): bpy.utils.register_module(__name__) # Add "Extras" menu to the "Add Curve" menu bpy.types.INFO_MT_curve_add.append(menu_func) + # Add "Extras" menu to the "Add Surface" menu + bpy.types.INFO_MT_surface_add.append(menu_surface) def unregister(): bpy.utils.unregister_module(__name__) # Remove "Extras" menu from the "Add Curve" menu. bpy.types.INFO_MT_curve_add.remove(menu_func) + # Remove "Extras" menu from the "Add Surface" menu. + bpy.types.INFO_MT_surface_add.remove(menu_surface) if __name__ == "__main__": register() diff --git a/add_curve_extra_objects/add_curve_aceous_galore.py b/add_curve_extra_objects/add_curve_aceous_galore.py index 13fda4be..41bf4587 100644 --- a/add_curve_extra_objects/add_curve_aceous_galore.py +++ b/add_curve_extra_objects/add_curve_aceous_galore.py @@ -44,8 +44,13 @@ from mathutils import ( Matrix, Vector, ) -from math import sin, cos, pi +from math import ( + sin, + cos, + pi + ) import mathutils.noise as Noise +from bpy.types import Operator ###------------------------------------------------------------ #### Some functions to use with others: ###------------------------------------------------------------ @@ -767,7 +772,7 @@ def main(context, self, align_matrix): return -class Curveaceous_galore(bpy.types.Operator): +class Curveaceous_galore(Operator): """Add many types of curves""" bl_idname = "mesh.curveaceous_galore" bl_label = "Curve Profiles" diff --git a/add_curve_extra_objects/add_curve_spirals.py b/add_curve_extra_objects/add_curve_spirals.py index a07ef411..29a86870 100644 --- a/add_curve_extra_objects/add_curve_spirals.py +++ b/add_curve_extra_objects/add_curve_spirals.py @@ -19,18 +19,25 @@ from bpy.props import ( FloatProperty, IntProperty, ) -from math import sin, cos, pi, exp +from math import ( + sin, + cos, + pi, + exp + ) from bpy_extras.object_utils import AddObjectHelper, object_data_add +from bpy.types import Operator #make normal spiral #----------------------------------------------------------------------------- -def make_spiral(props, context): #archemedian and logarithmic can be plottet in zylindrical coordinates - #if props.spiral_type != 1 and props.spiral_type != 2: - # return None +def make_spiral(props, context): +#archemedian and logarithmic can be plottet in zylindrical coordinates +#if props.spiral_type != 1 and props.spiral_type != 2: +# return None - #INPUT: turns->degree->max_phi, steps, direction - #Initialise Polar Coordinate Enviroment - #------------------------------- +#INPUT: turns->degree->max_phi, steps, direction +#Initialise Polar Coordinate Enviroment +#------------------------------- props.degree = 360*props.turns #If you want to make the slider for degree steps = props.steps * props.turns #props.steps[per turn] -> steps[for the whole spiral] props.z_scale = props.dif_z * props.turns @@ -47,25 +54,26 @@ def make_spiral(props, context): #archemedian and logarithmic c cur_phi = 0 cur_z = 0 - #------------------------------- +#------------------------------- - #Archemedean: dif_radius, radius +#Archemedean: dif_radius, radius cur_rad = props.radius - step_rad = props.dif_radius/(steps * 360/props.degree) #radius increase per angle for archemedean spiral| (steps * 360/props.degree)...Steps needed for 360 deg - #Logarithmic: radius, B_force, ang_div, dif_z + step_rad = props.dif_radius/(steps * 360/props.degree) +#radius increase per angle for archemedean spiral| (steps * 360/props.degree)...Steps needed for 360 deg +#Logarithmic: radius, B_force, ang_div, dif_z - #print("max_phi:",max_phi,"step_phi:",step_phi,"step_rad:",step_rad,"step_z:",step_z) +#print("max_phi:",max_phi,"step_phi:",step_phi,"step_rad:",step_rad,"step_z:",step_z) while abs(cur_phi) <= abs(max_phi): cur_phi += step_phi cur_z += step_z - #------------------------------- +#------------------------------- if props.spiral_type == 1: cur_rad += step_rad if props.spiral_type == 2: - #r = a*e^{|theta| * b} +#r = a*e^{|theta| * b} cur_rad = props.radius * pow(props.B_force, abs(cur_phi)) - #------------------------------- +#------------------------------- px = cur_rad * cos(cur_phi) py = cur_rad * sin(cur_phi) @@ -92,13 +100,13 @@ def make_spiral_spheric(props, context): verts = [] verts.extend([0,0,-props.radius,1]) #First vertex at south pole - #cur_rad = props.radius = CONST +#cur_rad = props.radius = CONST cur_phi = 0 cur_theta = -pi/2 #Beginning at south pole while abs(cur_phi) <= abs(max_phi): - #Coordinate Transformation sphere->rect +#Coordinate Transformation sphere->rect px = props.radius * cos(cur_theta) * cos(cur_phi) py = props.radius * cos(cur_theta) * sin(cur_phi) pz = props.radius * sin(cur_theta) @@ -113,7 +121,7 @@ def make_spiral_spheric(props, context): #----------------------------------------------------------------------------- def make_spiral_torus(props, context): - #INPUT: turns, steps, inner_radius, curves_number, mul_height, dif_inner_radius, cycles +#INPUT: turns, steps, inner_radius, curves_number, mul_height, dif_inner_radius, cycles max_phi = 2*pi*props.turns * props.cycles #max angle in radian step_phi = 2*pi/props.steps #Step of angle in radians between two vertices if props.spiral_direction == 1: #flip direction @@ -134,7 +142,7 @@ def make_spiral_torus(props, context): n_cycle = 0 while abs(cur_phi) <= abs(max_phi): - #Torus Coordinates -> Rect +#Torus Coordinates -> Rect px = ( cur_rad + cur_inner_rad * cos(cur_phi) ) * cos(props.curves_number * cur_theta) py = ( cur_rad + cur_inner_rad * cos(cur_phi) ) * sin(props.curves_number * cur_theta) pz = cur_inner_rad * sin(cur_phi) + cur_z @@ -172,14 +180,16 @@ def draw_curve(props, context): elif props.curve_type == 1: spline = curve_data.splines.new(type='NURBS') - spline.points.add( len(verts)*0.25-1 ) #Add only one quarter of points as elements in verts, because verts looks like: "x,y,z,?,x,y,z,?,x,..." + spline.points.add( len(verts)*0.25-1 ) +#Add only one quarter of points as elements in verts, because verts looks like: "x,y,z,?,x,y,z,?,x,..." spline.points.foreach_set('co', verts) new_obj = object_data_add(context, curve_data) -class spirals(bpy.types.Operator): +class spirals(Operator): bl_idname = "curve.spirals" bl_label = "Spirals" - bl_options = {'REGISTER','UNDO', 'PRESET'} #UNDO needed for operator redo and therefore also to let the addobjecthelp appear!!! + bl_options = {'REGISTER','UNDO', 'PRESET'} +#UNDO needed for operator redo and therefore also to let the addobjecthelp appear!!! bl_description = "adds different types of spirals" spiral_type = IntProperty(default=1, min=1, max=4, description="1:archemedian, 2:logarithmic, 3:spheric, 4:torus") @@ -191,12 +201,14 @@ class spirals(bpy.types.Operator): radius = FloatProperty(default=1.00, min=0.00, max=100.00, description="radius for first turn") - dif_z = FloatProperty(default=0, min=-10.00, max=100.00, description="increase in z axis per turn") #needed for 1 and 2 spiral_type - #ARCHMEDEAN variables - dif_radius = FloatProperty(default=0.00, min=-50.00, max=50.00, description="radius increment in each turn") #step between turns(one turn equals 360 deg) - #LOG variables + dif_z = FloatProperty(default=0, min=-10.00, max=100.00, description="increase in z axis per turn") +#needed for 1 and 2 spiral_type +#ARCHMEDEAN variables + dif_radius = FloatProperty(default=0.00, min=-50.00, max=50.00, description="radius increment in each turn") +#step between turns(one turn equals 360 deg) +#LOG variables B_force = FloatProperty(default=1.00, min=0.00, max=30.00, description="factor of exponent") - #TORUS variables +#TORUS variables inner_radius = FloatProperty(default=0.20, min=0.00, max=100, description="Inner Radius of Torus") dif_inner_radius = FloatProperty(default=0, min=-10, max=100, description="Increase of inner Radius per Cycle") dif_radius = FloatProperty(default=0, min=-10, max=100, description="Increase of Torus Radius per Cycle") @@ -204,7 +216,7 @@ class spirals(bpy.types.Operator): curves_number = IntProperty(default=1, min=1, max=400, description="Number of curves of spiral") touch = BoolProperty(default=False, description="No empty spaces between cycles") - def draw(self, context): #Function used by Blender to draw the menu + def draw(self, context): layout = self.layout layout.prop(self, 'spiral_type', text="Spiral Type") layout.prop(self, 'curve_type', text="Curve Type") @@ -242,7 +254,8 @@ class spirals(bpy.types.Operator): box.prop(self, 'dif_inner_radius', text = "Increase of Inner Radius") @classmethod - def poll(cls, context): #method called by blender to check if the operator can be run + def poll(cls, context): +#method called by blender to check if the operator can be run return context.scene != None def execute(self, context): time_start = time.time() diff --git a/add_curve_extra_objects/add_curve_torus_knots.py b/add_curve_extra_objects/add_curve_torus_knots.py index 7423be04..b43bd831 100644 --- a/add_curve_extra_objects/add_curve_torus_knots.py +++ b/add_curve_extra_objects/add_curve_torus_knots.py @@ -34,11 +34,22 @@ bl_info = { #### import modules import bpy -from bpy.props import BoolProperty, EnumProperty, FloatProperty, IntProperty -from math import sin, cos, pi, sqrt +from bpy.props import ( + BoolProperty, + EnumProperty, + FloatProperty, + IntProperty + ) +from math import ( + sin, + cos, + pi, + sqrt + ) from mathutils import * from bpy_extras.object_utils import AddObjectHelper, object_data_add from random import random +from bpy.types import Operator DEBUG = False @@ -59,7 +70,7 @@ def Torus_Knot(self, linkIndex=0): N = self.torus_res # curve resolution (number of control points) - # use plus options only when they are enabled +# use plus options only when they are enabled if self.options_plus: u = self.torus_u # p multiplier v = self.torus_v # q multiplier @@ -74,19 +85,19 @@ def Torus_Knot(self, linkIndex=0): R = self.torus_R * s # major radius (scaled) r = self.torus_r * s # minor radius (scaled) - # number of decoupled links when (p,q) are NOT co-primes +# number of decoupled links when (p,q) are NOT co-primes links = gcd(p,q) # = 1 when (p,q) are co-primes - # parametrized angle increment (cached outside of the loop for performance) - # NOTE: the total angle is divided by number of decoupled links to ensure - # the curve does not overlap with itself when (p,q) are not co-primes +# parametrized angle increment (cached outside of the loop for performance) +# NOTE: the total angle is divided by number of decoupled links to ensure +# the curve does not overlap with itself when (p,q) are not co-primes da = 2*pi/links/(N-1) - # link phase : each decoupled link is phased equally around the torus center - # NOTE: linkIndex value is in [0, links-1] +# link phase : each decoupled link is phased equally around the torus center +# NOTE: linkIndex value is in [0, links-1] linkPhase = 2*pi/q * linkIndex # = 0 when there is just ONE link - # user defined phasing +# user defined phasing if self.options_plus: rPhase = self.torus_rP # user defined revolution phase sPhase = self.torus_sP # user defined spin phase @@ -105,14 +116,14 @@ def Torus_Knot(self, linkIndex=0): print("link phase = %.2f deg" % (linkPhase * 180/pi)) print("link phase = %.2f rad" % linkPhase) - # flip directions ? NOTE: flipping both is equivalent to no flip +# flip directions ? NOTE: flipping both is equivalent to no flip if self.flip_p: p*=-1 if self.flip_q: q*=-1 - # create the 3D point array for the current link +# create the 3D point array for the current link newPoints = [] for n in range(N-1): - # t = 2*pi / links * n/(N-1) with: da = 2*pi/links/(N-1) => t = n * da +# t = 2*pi / links * n/(N-1) with: da = 2*pi/links/(N-1) => t = n * da t = n * da theta = p*t*u + rPhase # revolution angle phi = q*t*v + sPhase # spin angle @@ -121,8 +132,8 @@ def Torus_Knot(self, linkIndex=0): y = (R + r*cos(phi)) * sin(theta) z = r*sin(phi) * h - # append 3D point - # NOTE : the array is adjusted later as needed to 4D for POLY and NURBS +# append 3D point +# NOTE : the array is adjusted later as needed to 4D for POLY and NURBS newPoints.append([x,y,z]) return newPoints @@ -135,7 +146,7 @@ def align_matrix(self, context): else: loc = Matrix.Translation(context.scene.cursor_location) - # user defined location & translation +# user defined location & translation userLoc = Matrix.Translation(self.location) userRot = self.rotation.to_matrix().to_4x4() @@ -163,15 +174,15 @@ def setBezierHandles(obj, mode = 'AUTOMATIC'): # ------------------------------------------------------------------------------ # Convert array of vert coordinates to points according to spline type def vertsToPoints(Verts, splineType): - # main vars +# main vars vertArray = [] - # array for BEZIER spline output (V3) +# array for BEZIER spline output (V3) if splineType == 'BEZIER': for v in Verts: vertArray += v - # array for non-BEZIER output (V4) +# array for non-BEZIER output (V4) else: for v in Verts: vertArray += v @@ -185,33 +196,33 @@ def vertsToPoints(Verts, splineType): # ------------------------------------------------------------------------------ # Create the Torus Knot curve and object and add it to the scene def create_torus_knot(self, context): - # pick a name based on (p,q) parameters +# pick a name based on (p,q) parameters aName = "Torus Knot %i x %i" % (self.torus_p, self.torus_q) - # create curve +# create curve curve_data = bpy.data.curves.new(name=aName, type='CURVE') - # setup materials to be used for the TK links +# setup materials to be used for the TK links if self.use_colors: addLinkColors(self, curve_data) - # create torus knot link(s) +# create torus knot link(s) if self.multiple_links: links = gcd(self.torus_p, self.torus_q); else: links = 1; for l in range(links): - # get vertices for the current link +# get vertices for the current link verts = Torus_Knot(self, l) - # output splineType 'POLY' 'NURBS' or 'BEZIER' +# output splineType 'POLY' 'NURBS' or 'BEZIER' splineType = self.outputType - # turn verts into proper array (based on spline type) +# turn verts into proper array (based on spline type) vertArray = vertsToPoints(verts, splineType) - # create spline from vertArray (based on spline type) +# create spline from vertArray (based on spline type) spline = curve_data.splines.new(type=splineType) if splineType == 'BEZIER': spline.bezier_points.add(int(len(vertArray)*1.0/3-1)) @@ -221,18 +232,18 @@ def create_torus_knot(self, context): spline.points.foreach_set('co', vertArray) spline.use_endpoint_u = True - # set curve options +# set curve options spline.use_cyclic_u = True spline.order_u = 4 - # set a color per link +# set a color per link if self.use_colors: spline.material_index = l curve_data.dimensions = '3D' curve_data.resolution_u = self.segment_res - # create surface ? +# create surface ? if self.geo_surface: curve_data.fill_mode = 'FULL' curve_data.bevel_depth = self.geo_bDepth @@ -242,14 +253,14 @@ def create_torus_knot(self, context): new_obj = bpy.data.objects.new(aName, curve_data) - # set object in the scene +# set object in the scene scene = bpy.context.scene scene.objects.link(new_obj) # place in active scene new_obj.select = True # set as selected scene.objects.active = new_obj # set as active new_obj.matrix_world = self.align_matrix # apply matrix - # set BEZIER handles +# set BEZIER handles if splineType == 'BEZIER': setBezierHandles(new_obj, self.handleType) @@ -258,7 +269,7 @@ def create_torus_knot(self, context): # ------------------------------------------------------------------------------ # Create materials to be assigned to each TK link def addLinkColors(self, curveData): - # some predefined colors for the torus knot links +# some predefined colors for the torus knot links colors = [] if self.colorSet == "1": # RGBish colors += [ [0.0, 0.0, 1.0] ] @@ -288,7 +299,7 @@ def addLinkColors(self, curveData): for i in range(links): matName = "TorusKnot-Link-%i" % i matListNames = bpy.data.materials.keys() - # create the material +# create the material if matName not in matListNames: if DEBUG: print("Creating new material : %s" % matName) mat = bpy.data.materials.new(matName) @@ -296,7 +307,7 @@ def addLinkColors(self, curveData): if DEBUG: print("Material %s already exists" % matName) mat = bpy.data.materials[matName] - # set material color +# set material color if self.options_plus and self.random_colors: mat.diffuse_color = random(), random(), random() else: @@ -312,7 +323,7 @@ def addLinkColors(self, curveData): # ------------------------------------------------------------------------------ # Main Torus Knot class -class torus_knot_plus(bpy.types.Operator, AddObjectHelper): +class torus_knot_plus(Operator, AddObjectHelper): """""" bl_idname = "curve.torus_knot_plus" bl_label = "Torus Knot +" @@ -321,15 +332,15 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): bl_context = "object" def mode_update_callback(self, context): - # keep the equivalent radii sets (R,r)/(eR,iR) in sync +# keep the equivalent radii sets (R,r)/(eR,iR) in sync if self.mode == 'EXT_INT': self.torus_eR = self.torus_R + self.torus_r self.torus_iR = self.torus_R - self.torus_r - # align_matrix for the invoke +# align_matrix for the invoke align_matrix = None - #### GENERAL options +#### GENERAL options options_plus = BoolProperty( name="Extra Options", default=False, @@ -341,7 +352,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): description="Set absolute location instead of relative to 3D cursor", ) - #### COLOR options +#### COLOR options use_colors = BoolProperty( name="Use Colors", default=False, @@ -364,7 +375,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): description="Color saturation", ) - #### SURFACE Options +#### SURFACE Options geo_surface = BoolProperty( name="Surface", default=True, @@ -396,7 +407,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): description="Offset the surface relative to the curve" ) - #### TORUS KNOT Options +#### TORUS KNOT Options torus_p = IntProperty( name="p", default=2, @@ -449,7 +460,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): description="Phase spins by this radian amount" ) - #### TORUS DIMENSIONS options +#### TORUS DIMENSIONS options mode = EnumProperty( name="Torus Dimensions", items=(("MAJOR_MINOR", "Major/Minor", @@ -503,7 +514,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): description="Scale along the local Z axis" ) - #### CURVE options +#### CURVE options torus_res = IntProperty( name="Curve Resolution", default=100, @@ -542,14 +553,14 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): description="Auto adjust curve resolution based on TK length", ) - ##### DRAW ##### +##### DRAW ##### def draw(self, context): layout = self.layout - # extra parameters toggle +# extra parameters toggle layout.prop(self, 'options_plus') - # TORUS KNOT Parameters +# TORUS KNOT Parameters col = layout.column() col.label(text="Torus Knot Parameters:") box = layout.box() @@ -572,7 +583,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): box.prop(self, 'torus_rP') box.prop(self, 'torus_sP') - # TORUS DIMENSIONS options +# TORUS DIMENSIONS options col = layout.column(align=True) col.label(text="Torus Dimensions:") box = layout.box() @@ -597,7 +608,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): box.prop(self, 'torus_s') box.prop(self, 'torus_h') - # CURVE options +# CURVE options col = layout.column(align=True) col.label(text="Curve Options:") box = layout.box() @@ -608,13 +619,13 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): depends=box.column() depends.prop(self, 'torus_res') - # deactivate the "curve resolution" if "adaptive resolution" is enabled +# deactivate the "curve resolution" if "adaptive resolution" is enabled depends.enabled = not self.adaptive_resolution box.prop(self, 'adaptive_resolution') box.prop(self, 'segment_res') - # SURFACE options +# SURFACE options col = layout.column() col.label(text="Geometry Options:") box = layout.box() @@ -625,7 +636,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): box.prop(self, 'geo_extrude') box.prop(self, 'geo_offset') - # COLOR options +# COLOR options col = layout.column() col.label(text="Color Options:") box = layout.box() @@ -636,7 +647,7 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): box.prop(self, 'random_colors') box.prop(self, 'saturation') - # TRANSFORM options +# TRANSFORM options col = layout.column() col.label(text="Transform Options:") box = col.box() @@ -644,49 +655,49 @@ class torus_knot_plus(bpy.types.Operator, AddObjectHelper): box.prop(self, 'absolute_location') box.prop(self, 'rotation') - ##### POLL ##### +##### POLL ##### @classmethod def poll(cls, context): if context.mode != "OBJECT": return False return context.scene != None - ##### EXECUTE ##### +##### EXECUTE ##### def execute(self, context): if self.mode == 'EXT_INT': - # adjust the equivalent radii pair : (R,r) <=> (eR,iR) +# adjust the equivalent radii pair : (R,r) <=> (eR,iR) self.torus_R = (self.torus_eR + self.torus_iR)*0.5 self.torus_r = (self.torus_eR - self.torus_iR)*0.5 if self.adaptive_resolution: - # adjust curve resolution automatically based on (p,q,R,r) values +# adjust curve resolution automatically based on (p,q,R,r) values p = self.torus_p q = self.torus_q R = self.torus_R r = self.torus_r links = gcd(p,q) - # get an approximate length of the whole TK curve +# get an approximate length of the whole TK curve maxTKLen = 2*pi*sqrt(p*p*(R+r)*(R+r) + q*q*r*r) # upper bound approximation minTKLen = 2*pi*sqrt(p*p*(R-r)*(R-r) + q*q*r*r) # lower bound approximation avgTKLen = (minTKLen + maxTKLen)/2 # average approximation if DEBUG: print("Approximate average TK length = %.2f" % avgTKLen) self.torus_res = max(3, avgTKLen/links * 8) # x N factor = control points per unit length - # update align matrix +# update align matrix self.align_matrix = align_matrix(self, context) - # turn off undo +# turn off undo undo = bpy.context.user_preferences.edit.use_global_undo bpy.context.user_preferences.edit.use_global_undo = False - # create the curve +# create the curve create_torus_knot(self, context) - # restore pre operator undo state +# restore pre operator undo state bpy.context.user_preferences.edit.use_global_undo = undo return {'FINISHED'} - ##### INVOKE ##### +##### INVOKE ##### def invoke(self, context, event): self.execute(context) diff --git a/add_curve_extra_objects/add_surface_plane_cone.py b/add_curve_extra_objects/add_surface_plane_cone.py new file mode 100644 index 00000000..4e0a1e4b --- /dev/null +++ b/add_curve_extra_objects/add_surface_plane_cone.py @@ -0,0 +1,451 @@ +bl_info = { + "name": "Surface: plane/cone/star/wedge", + "description": "create a NURBS surface plane.", + "author": "Folkert de Vries", + "version": (1, 0), + "blender": (2, 5, 9), + "api": 31236, + "location": "View3D > Add> Surface", + "warning": '', # used for warning icon and text in addons panel + "wiki_url": " "\ + " ", + "tracker_url": " "\ + " ", + "category": "Add Mesh" +} + +# info: +''' +to add a surface star, plane or cone, go to add menu>surface>star,plane or cone +next parameters like scale and u and v resolution can be adjusted in the toolshelf. + +have fun using this addon +''' + + +import bpy +from bpy.props import ( + FloatProperty, + IntProperty, + ) + +from bpy.types import Operator + + +class MakeSurfaceWedge(Operator): + bl_idname = 'object.add_surface_wedge' + bl_label = 'Add Surface Wedge' + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_context = "object" + bl_options = {'REGISTER', 'UNDO'} +# get input for size and resolution + + size = FloatProperty(name="Size", + description="Size of the object.", + default=1.0, + min=0.01, + max=100.0, + unit="LENGTH") + res_u = IntProperty(name="Resolution U", + description="Surface resolution in u direction", + default=1, + min=1, + max=500) + res_v = IntProperty(name="Resolution V", + description="Surface resolution in v direction", + default=1, + min=1, + max=500) + + def execute(self, context): + # variables + size = self.size + res_u = self.res_u + res_v = self.res_v + # add a surface Plane + bpy.ops.object.add_surface_plane() + # save some time, by getting instant acces to those values. + ao = bpy.context.active_object + point = ao.data.splines[0].points + # rotate 90 degrees on the z axis + ao.rotation_euler[0] = 0.0 + ao.rotation_euler[1] = 0.0 + ao.rotation_euler[2] = 1.570796 + # go into edit mode and deselect + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.curve.select_all(action='DESELECT') + # select points 0 and 1, and extrudde them + # declaring ao and point again seems necesary... + ao = bpy.context.active_object + point = ao.data.splines[0].points + point[0].select = True + ao = bpy.context.active_object + point = ao.data.splines[0].points + point[1].select = True + bpy.ops.curve.extrude() + # bring extruded points up 1 bu on the z axis, and toggle + # cyclic in V direction + bpy.ops.transform.translate(value=(0, 0, 1), constraint_axis=(False, False, True)) + bpy.ops.curve.cyclic_toggle(direction='CYCLIC_V') + + # get points to the right coords. + point[0].co = (1.0, 0.0, 1.0, 1.0) + point[1].co = (-1.0, 0.0, 1.0, 1.0) + point[2].co = (1.0, -0.5, 0.0, 1.0) + point[3].co = (-1.0, -0.5, 0.0, 1.0) + point[4].co = (1.0, 0.5, 0.0, 1.0) + point[5].co = (-1.0, 0.5, 0.0, 1.0) + + # go back to object mode + bpy.ops.object.mode_set(mode='OBJECT') + # get origin to geometry. + bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN') + # change name + bpy.context.active_object.name = 'SurfaceWedge' + # get the wedge to the 3d cursor. + bpy.context.active_object.location = bpy.context.scene.cursor_location + bpy.ops.transform.resize(value=(size, size, size)) + + # adjust resolution in u and v direction + bpy.context.active_object.data.resolution_u = res_u + bpy.context.active_object.data.resolution_v = res_v + + return{'FINISHED'} + + positions = [(1.0, 1.0, -1.0, 1.0), (1.0, -1.0, -1.0, 1.0), (-1.0, -1.0, -1.0, 1.0), (-1.0, 1.0, -1.0, 1.0), (1.0, 0.0, 1.0, 1.0), (-1.0, 0.0, 1.0, 1.0)] + + +class MakeSurfaceCone(Operator): + bl_idname = 'object.add_surface_cone' + bl_label = 'Add Surface Cone' + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_context = "object" + bl_options = {'REGISTER', 'UNDO'} + + size = FloatProperty(name="Size", + description="Size of the object.", + default=1.0, + min=0.01, + max=100.0, + unit="LENGTH") + res_u = IntProperty(name="Resolution U", + description="Surface resolution in u direction", + default=4, + min=1, + max=500) + res_v = IntProperty(name="Resolution V", + description="Surface resolution in v direction", + default=4, + min=1, + max=500) + + def execute(self, context): + size = self.size + res_u = self.res_u + res_v = self.res_v + + # add basemesh, a nurbs torus + bpy.ops.surface.primitive_nurbs_surface_torus_add(location=(0, 0, 0)) + # get active object and active object name + ao = bpy.context.active_object + aoname = bpy.context.active_object.name + # go to edit mode + bpy.ops.object.mode_set(mode='EDIT') + # deselect all + bpy.ops.curve.select_all(action='DESELECT') + # too shorten alot of lines + point = ao.data.splines[0].points + # get middle points + + for i in range(0, 63): + if point[i].co.z == 0.0: + point[i].select = True + + # select non-middle points and delete them + bpy.ops.curve.select_all(action='INVERT') + bpy.ops.curve.delete(type='VERT') + # declaring this again seems necesary... + point = ao.data.splines[0].points + # list of points to be in center, and 2 bu'' s higher + + ToKeep = [1, 3, 5, 7, 9, 11, 13, 15, 17] + for i in range(0, len(ToKeep) - 1): + point[ToKeep[i]].select = True + bpy.ops.transform.resize(value=(0, 0, 0)) + bpy.ops.curve.cyclic_toggle(direction='CYCLIC_U') + bpy.ops.transform.translate(value=(0, 0, 2)) + + # to make cone visible + bpy.ops.object.editmode_toggle() + bpy.ops.object.editmode_toggle() + # change name + bpy.context.active_object.name = 'SurfaceCone' + # go back to object mode + bpy.ops.object.editmode_toggle() + # bring object to cursor + bpy.ops.object.mode_set(mode='OBJECT') + bpy.context.active_object.location = bpy.context.scene.cursor_location + # adjust size + bpy.ops.transform.resize(value=(size, size, size)) + + # adjust resolution in u and v direction + bpy.context.active_object.data.resolution_u = res_u + bpy.context.active_object.data.resolution_v = res_v + + return{'FINISHED'} + + +class MakeSurfaceStar(Operator): + bl_idname = 'object.add_surface_star' + bl_label = 'Add Surface Star' + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_context = "object" + bl_options = {'REGISTER', 'UNDO'} + + size = FloatProperty(name="Size", + description="Size of the object.", + default=1.0, + min=0.01, + max=100.0, + unit="LENGTH") + res_u = IntProperty(name="Resolution U", + description="Surface resolution in u direction", + default=1, + min=1, + max=500) + res_v = IntProperty(name="Resolution V", + description="Surface resolution in v direction", + default=1, + min=1, + max=500) + + def execute(self, context): + size = self.size + res_u = self.res_u + res_v = self.res_v + + # add surface circle: + bpy.ops.surface.primitive_nurbs_surface_circle_add(location=(0, 0, 0)) + # we got 8 points, we need 40 points. + # get active object + ao = bpy.context.active_object + # enter edtimode + bpy.ops.object.mode_set(mode='EDIT') + # deselect all + bpy.ops.curve.select_all(action='DESELECT') + # select point 0 and 1, and subdivide + point = ao.data.splines[0].points + + point[0].select = True + point[1].select = True + bpy.ops.curve.subdivide() + bpy.ops.curve.select_all(action='DESELECT') + + # select point 2 and 3, and subdivide + point[2].select = True + point[3].select = True + bpy.ops.curve.subdivide() + bpy.ops.curve.select_all(action='DESELECT') + + ListOfCoords = [(0.5, 0.0, 0.25, 1.0), + (0.80901700258255, 0.5877853035926819, 0.25, 1.0), + (0.1545085906982422, 0.4755282402038574, 0.25, 1.0), + (-0.30901703238487244, 0.9510565400123596, 0.25, 1.0), + (-0.4045085608959198, 0.293892502784729, 0.2499999850988388, 1.0), + (-1.0, 0.0, 0.25, 1.0), + (-0.4045085608959198, -0.293892502784729, 0.2499999850988388, 1.0), + (-0.30901703238487244, -0.9510565400123596, 0.25, 1.0), + (0.1545085906982422, -0.4755282402038574, 0.25, 1.0), + (0.8090166449546814, -0.5877856612205505, 0.2499999850988388, 1.0)] + for i in range(0, 10): + bpy.context.active_object.data.splines[0].points[i].co = ListOfCoords[i] + + # now select all, and subdivide till 40 points is reached: + bpy.ops.curve.select_all(action='SELECT') + bpy.ops.curve.subdivide() + bpy.ops.curve.subdivide() + bpy.ops.curve.subdivide() + + # extrude the star + bpy.ops.curve.extrude(mode='TRANSLATION') + # bring extruded part up + bpy.ops.transform.translate(value=(0, 0, 0.5), constraint_axis=(False, False, True)) + # flip normals + bpy.ops.curve.switch_direction() + # go back to object mode + bpy.ops.object.mode_set(mode='OBJECT') + # origin to geometry + bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN') + # get object to 3d cursor + bpy.context.active_object.location = bpy.context.scene.cursor_location + # change name + ao.name = 'SurfaceStar' + # adjust size + bpy.ops.transform.resize(value=(size, size, size)) + + # adjust resolution in u and v direction + bpy.context.active_object.data.resolution_u = res_u + bpy.context.active_object.data.resolution_v = res_v + + return{'FINISHED'} + + +class MakeSurfacePlane(Operator): + bl_idname = 'object.add_surface_plane' + bl_label = 'Add Surface Plane' + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_context = "object" + bl_options = {'REGISTER', 'UNDO'} + + size = FloatProperty(name="Size", + description="Size of the object.", + default=1.0, + min=0.01, + max=100.0, + unit="LENGTH") + res_u = IntProperty(name="Resolution U", + description="Surface resolution in u direction", + default=1, + min=1, + max=500) + res_v = IntProperty(name="Resolution V", + description="Surface resolution in v direction", + default=1, + min=1, + max=500) + + def execute(self, context): + size = self.size + res_u = self.res_u + res_v = self.res_v + + bpy.ops.surface.primitive_nurbs_surface_surface_add() # add the base mesh, a NURBS Surface + + bpy.ops.transform.resize(value=(1, 1, 0.0001), constraint_axis=(False, False, True)) # make it flat + ao = bpy.context.active_object.name # get the active object' s name + # added surface has 16 points + + # deleting points to get plane shape. + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.curve.select_all(action='DESELECT') + + bpy.context.active_object.data.splines[0].points[0].select = True + bpy.context.active_object.data.splines[0].points[1].select = True + bpy.context.active_object.data.splines[0].points[2].select = True + bpy.context.active_object.data.splines[0].points[3].select = True + bpy.ops.curve.delete(type='VERT') + + bpy.context.active_object.data.splines[0].points[8].select = True + bpy.context.active_object.data.splines[0].points[9].select = True + bpy.context.active_object.data.splines[0].points[10].select = True + bpy.context.active_object.data.splines[0].points[11].select = True + bpy.ops.curve.delete(type='VERT') + + bpy.context.active_object.data.splines[0].points[0].select = True + bpy.context.active_object.data.splines[0].points[4].select = True + bpy.ops.curve.delete(type='VERT') + bpy.context.active_object.data.splines[0].points[2].select = True + bpy.context.active_object.data.splines[0].points[5].select = True + bpy.ops.curve.delete(type='VERT') + + # assigning name + bpy.context.active_object.name = 'SurfacePlane' + # select all + bpy.ops.curve.select_all(action='SELECT') + # bringing origin to center: + bpy.ops.object.mode_set(mode='OBJECT') + bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN') + # transform scale + bpy.ops.object.transform_apply(scale=True) + # bring object to 3d cursor. + bpy.ops.object.mode_set(mode='OBJECT') + bpy.context.active_object.location = bpy.context.scene.cursor_location + bpy.ops.transform.resize(value=(size, size, size)) + + # adjust resolution in u and v direction + bpy.context.active_object.data.resolution_u = res_u + bpy.context.active_object.data.resolution_v = res_v + + return{'FINISHED'} + + +class SmoothXtimes(Operator): + bl_idname = 'curve.smooth_x_times' + bl_label = 'Smooth X Times' + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_context = "object" + bl_options = {'REGISTER', 'UNDO'} + '''use of this class: + lets you smooth till a thousand times. this is normally difficult, because + you have to press w, click, press w, click ect.''' + + # get values + times = IntProperty(name='smooth x times', + min=1, + max=1000, + default=1, + description='amount of smooths') + + def execute(self, context): + # smooth times time(s). + times = self.times + for i in range(1, times): + bpy.ops.curve.smooth() + return{'FINISHED'} + + +def Surface_plane_button(self, context): + self.layout.operator(MakeSurfacePlane.bl_idname, text="surface plane", icon="MOD_CURVE") + + +def Surface_cone_button(self, context): + self.layout.operator(MakeSurfaceCone.bl_idname, text="surface cone", icon="MOD_CURVE") + + +def Surface_star_button(self, context): + self.layout.operator(MakeSurfaceStar.bl_idname, text="surface star", icon="MOD_CURVE") + + +def Surface_wedge_button(self, context): + self.layout.operator(MakeSurfaceWedge.bl_idname, text="surface wedge", icon="MOD_CURVE") + + +def SmoothXtimes_button(self, context): + self.layout.operator(SmoothXtimes.bl_idname, text="smooth x times", icon="MOD_CURVE") + + +def register(): + bpy.utils.register_class(UserInterface) + bpy.utils.register_class(MakeSurfacePlane) + bpy.utils.register_class(MakeSurfaceCone) + bpy.utils.register_class(MakeSurfaceStar) + bpy.utils.register_class(MakeSurfaceWedge) + bpy.utils.register_class(SmoothXtimes) + bpy.types.INFO_MT_surface_add.append(Surface_plane_button) + bpy.types.INFO_MT_surface_add.append(Surface_cone_button) + bpy.types.INFO_MT_surface_add.append(Surface_star_button) + bpy.types.INFO_MT_surface_add.append(Surface_wedge_button) + bpy.types.VIEW3D_MT_edit_curve_specials.append(SmoothXtimes_button) + + +def unregister(): + bpy.utils.unregister_class(UserInterface) + bpy.utils.unregister_class(MakeSurfacePlane) + bpy.utils.unregister_class(MakeSurfaceCone) + bpy.utils.unregister_class(MakeSurfaceStar) + bpy.utils.unregister_class(MakeSurfaceWedge) + bpy.utils.unregister_class(SmoothXtimes) + bpy.types.INFO_MT_surface_add.remove(Surface_plane_button) + bpy.types.INFO_MT_surface_add.remove(Surface_cone_button) + bpy.types.INFO_MT_surface_add.remove(Surface_star_button) + bpy.types.INFO_MT_surface_add.remove(Surface_wedge_button) + bpy.types.VIEW3D_MT_edit_curve_specials.remove(SmoothXtimes_button) + + +if __name__ == "__main__": + register() -- cgit v1.2.3