Page MenuHome

XYFunctionSurface.py

XYFunctionSurface.py

# In the name of ALLAH(God)
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "X-Y Function",
"author":"Hadi Beygi(ISLAMIC REPUBLIK OF IRAN),[Buerbaum Martin (Pontiac),Elod Csirmaz]",
"version": (1, 0, 0),
"blender": (2, 6, 1),
"location": "View3D > Add > Mesh",
"description": "Draw X-Y functions using math formulas in five state(default,integral,up,down,around) and finds zero('s) of function (if exists).",
"tracker_url": "http://www.blender.ir/addons/xyfunctionsurface/",
"category": "Add Mesh"}
import bpy
from mathutils import *
from math import *
from bpy.props import *
# List of safe functions for eval()
safe_list = ['math', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh',
'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot',
'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians',
'sin', 'sinh', 'sqrt', 'tan', 'tanh']
# Use the list to filter the local namespace
safe_dict = dict((k, globals().get(k, None)) for k in safe_list)
# Stores the values of a list of properties and the
# operator id in a property group ('recall_op') inside the object.
# Could (in theory) be used for non-objects.
# Note: Replaces any existing property group with the same name!
# ob ... Object to store the properties in.
# op ... The operator that should be used.
# op_args ... A dictionary with valid Blender
# properties (operator arguments/parameters).
# Create a new mesh (object) from verts/edges/faces.
# verts/edges/faces ... List of vertices/edges/faces for the
# new mesh (as used in from_pydata).
# name ... Name of the new mesh (& object).
def create_mesh_object(context, verts, edges, faces, name):
# Create new mesh
mesh = bpy.data.meshes.new(name)
# Make a mesh from a list of verts/edges/faces.
mesh.from_pydata(verts, edges, faces)
# Update mesh geometry after adding stuff.
mesh.update()
from bpy_extras import object_utils
return object_utils.object_data_add(context, mesh, operator=None)
def find_zero(y_eq,x1,x2,n):
X=(x1+x2)/2
while round(x1,4)!=round(x2,4):
x=x1
y1=eval(y_eq)
x=x2
y2=eval(y_eq)
X=(x1+x2)/2
x=X
y=eval(y_eq)
if y==0.0:
break
elif y*y1<0:
x2=X
elif y*y2<0:
x1=X
return round(X,4)
def xy_function(self, y_eq, range_x_min, range_x_max, res_per_unit, n, fill):
verts, edges, faces = [],[],[]
zero=[] #a list contains index of y=0 points
if range_x_max<range_x_min:
t=range_x_max
range_x_max=range_x_min
range_x_min=t
x=range_x_max
y_max=eval(y_eq)
x=range_x_min
y_min=eval(y_eq)
# Distance of each step in Blender Units
Delta= range_x_max - range_x_min
resolution=int(Delta*res_per_unit)
if resolution==0 :
x_step=Delta
resolution=1
else:
x_step =1/res_per_unit
safe_dict['n'] = n
try:
expr_args_y = (
compile(y_eq, __file__, 'eval'),
{"__builtins__": None},
safe_dict)
except:
import traceback
self.report({'ERROR'}, "Error parsing expression: "
+ traceback.format_exc(limit=1))
return [], [], []
#calculate points
x=range_x_min
x1=range_x_min
try:
safe_dict['x'] = x
y1=float(eval(*expr_args_y)) # Try to evaluate the equations.
except:
pass
verts.append((x1,y1,0))
for i in range(resolution):
x = x1+x_step
try:
safe_dict['x'] = x
y=float(eval(*expr_args_y)) # Try to evaluate the equations.
except:
pass
if y==0.0:
verts.append((x,0,0))
#zero.append(i)
elif y1*y<0:
x_middle= find_zero(y_eq,x1,x,n) #find Zero of function y=0 => x=?
verts.append((x_middle,0,0))
#zero.append(i)
verts.append((x,y,0))
else:
verts.append((x,y,0))
if y1>y_max:
y_max=y1
if y1<y_min:
y_min=y1
y1=y
x1=x
L=[]
len_verts=len(verts)
if fill=='default':
edges=[(n,n+1)for n in range(len_verts-1)]
elif fill=='around':
len_verts -=1
faces=[(0,n,n+1) for n in range(1,len_verts)]
elif fill=='integral':
for i in verts:
L.append((i[0], 0, 0))
L.append(i)
verts=L
len_verts=len(verts)-2
while n<len_verts:
faces.append((n,n+1,n+3,n+2))
n+=2
elif fill=='up':
for i in verts:
L.append((i[0], y_max, 0))
L.append(i)
verts=L
len_verts=len(verts)-2
while n<len_verts:
faces.append((n,n+1,n+3,n+2))
n+=2
elif fill=='down':
for i in verts:
L.append((i[0], y_min, 0))
L.append(i)
verts=L
len_verts=len(verts)-2
while n<len_verts:
faces.append((n,n+1,n+3,n+2))
n+=2
return verts, edges, faces
class AddXYFunction(bpy.types.Operator):
'''Add a surface defined defined by function:''' \
+ ''' y=F(x,y)'''
bl_idname = "mesh.primitive_xy_function"
bl_label = "Add X-Y Function Surface"
bl_options = {'REGISTER', 'UNDO'}
y_eq = StringProperty(name="Y equation",
description="Equation for y=F(x,y). ",
default="sin(x)")
range_x_min = FloatProperty(name="X min",
description="Minimum X value. Lower boundary of X range",
min=-1000.00,
max=1000.00,
default=-10.00)
range_x_max = FloatProperty(name="X max",
description="Maximum X value. Upper boundary of X range",
min=-1000.00,
max=1000.00,
default=10.00)
fill_types=[('default','Default',''),
('integral','Integral',''),
('up','Up',''),
('down','Down',''),
('around','Around','')]
fill = EnumProperty( attr='fill_type',
name='Fill',
description='Choose the type of filling you would like',
items = fill_types,
default = 'integral')
n_eq = IntProperty(name="Number of objects (n=0..N-1)",
description="The parameter n will be the index " \
"of the current object, 0 to N-1",
min=1,
max=100,
default=1)
res_per_unit = IntProperty(name="Resolution per unit",
description="Number of points in 1 unit to calculate the function",
min=1,
max=1000,
default=10)
def execute(self, context):
for n in range(0, self.n_eq):
verts, edges, faces = xy_function(
self,
self.y_eq,
self.range_x_min,
self.range_x_max,
self.res_per_unit,
n,
self.fill)
if not verts:
return {'CANCELLED'}
print(verts)
obj = create_mesh_object(context, verts, edges, faces, 'XY_Function')
# remove doubles
#bpy.ops.mesh.remove_doubles(limit=0.0001)
return {'FINISHED'}
####Registeration
def AddXYFunction_menu(self, context):
self.layout.operator(AddXYFunction.bl_idname,icon='FCURVE')
def register():
bpy.utils.register_class(AddXYFunction)
# Add "AddXYFunctionSurface" to the "Add Mesh" menu
bpy.types.INFO_MT_mesh_add.prepend(AddXYFunction_menu)
def unregister():
bpy.utils.unregister_class(AddXYFunction)
# Remove "AddXYFunctionSurface" from the "Add Mesh" menu.
bpy.types.INFO_MT_mesh_add.remove(AddXYFunction_menu)
if __name__ == "__main__":
register()

File Metadata

Mime Type
text/x-python
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
17/07/ce759d70e0515be227c3357774fb

Event Timeline