How to create a 3D object from a specific equation

I realize this has been asked before, so I apologize for the "repeat". I saw this answer, and it mostly solved my issue. However, I can't figure out how to generate my specific equation. This is my equation: This works from the range -1 <= x <= 1. For the really big equation, the "x" should actually be z, and the "h" should be x (I had to use those to graph it on Desmos). In any case, I tried inputting the first half of the equation with the Blender Add Mesh: Extra Objects > Math Function > Z Math Surface by typing this:

(sqrt(-16*fabs(x)+40*sqrt(fabs(x))*y-16*pow(x,2)-25*pow(y,2)+16)+15*x)/15

The result is an error evaluating the expression. Do I have to set the range somehow? Would it be better to use XYZ Math Surface? (and if so, how?). Or am I just doing something wrong? Thank you in advance.

• Hi Lee. Not sure what you mean by 'two asterisks each'. Can you edit the question and put 4 spaces before the line with the code. This will disable the formatting so that you can enter it as-is. May 24 '17 at 6:30
• @RichSedman, Got it. I didn't know about adding four spaces. Thanks for the tip, the proper change has been made. May 26 '17 at 15:28

As @TLousky quite rightly points out, the problem is due to the evaluation of the equation throwing an exception due to the sqrt(...) function attempting to find the square root of a negative number (which doesn't have a 'real' answer).

To avoid the Z Equation from hitting this problem you can use a conditional assignment.

In Python you can assign a variable based on whether a certain condition is met as follows :

myvar = <value> if <condition> else <othervalue>

Where value is the value to assign if the condition is True and othervalue is the value to assign if the condition is False. The same style of conditional assignment can be used in Blender for the Z Equation.

In your example, the failure occurs because the contents of the initial sqrt(...) function evaluates below zero, so the condition to identify 'valid' values should be :

(-16*fabs(x)+40 * sqrt(fabs(x)) * y - 16 * pow(x,2) - 25 * pow(y,2) + 16)>=0.0

The value to assign if this condition is True would be :

( sqrt(-16*fabs(x)+40 * sqrt(fabs(x)) * y - 16 * pow(x,2) - 25 * pow(y,2) + 16)  + 15 * x)/15

And the value to assign if the condition is False would be :

(0 + 15 * x)/15

(ie, for values < 0 assume that sqrt(...) is zero)

Putting this all together, the Z Equation should be :

( sqrt(-16*fabs(x)+40 * sqrt(fabs(x)) * y - 16 * pow(x,2) - 25 * pow(y,2) + 16)  + 15 * x)/15 if (-16*fabs(x)+40 * sqrt(fabs(x)) * y - 16 * pow(x,2) - 25 * pow(y,2) + 16)>=0.0 else (0 + 15 * x)/15

And this should produce the following result : • Nice workaround! Quick note though: (0+15*x)/15 equals simply x, so would make the conditional simpler :) May 25 '17 at 12:48
• Well, that looks about exactly what I'm looking for. I didn't know you could use conditionals in the equation. That opens so many possibilities! Thanks for the answer! May 26 '17 at 15:33
• Would it be possible to, instead of having the conditional be that the squared function is greater than 0, that x is less than or equal to 1 and greater than or equal to -1? -1<=x<=1 I'm not sure if that would change the results, but it was how I initially set the function to work. Is that possible by saying [function] if x >= -1 AND x <= 1 else [alt function]? As it stands, I'm not sure why it's slanted like that. I thought it should be flat, perpendicular to the x-axis. May 26 '17 at 19:09
• You can use conditionals such as that, but equally you can set the range in the X Size and Y Size fields in the tool panel on the left. Setting X Size to 2 would naturally make it range from -1 to 1. Perhaps one of the terms in the equation is incorrect? May 26 '17 at 19:16
• Is it supposed to be a heart shape? If you remove the last bit you get "( sqrt(-16*fabs(x)+40 * sqrt(fabs(x)) * y - 16 * pow(x,2) - 25 * pow(y,2) + 16))/15 if (-16*fabs(x)+40 * sqrt(fabs(x)) * y - 16 * pow(x,2) - 25 * pow(y,2) + 16)>=0.0 else (0)" which does produce a heart shape on a flat plane. May 26 '17 at 19:21 The problem that prevents your equation from working with the Add Mesh: Extra Objects > Math Function > Z Math , is that you're using a sqrt function which is undefined for negative values.

When the math function operator tries to evaluate different values for X and Y, it raises an exception the first time that evaluation fails due to an attempt to sqrt a negative value.

Another option is to write a script of your own to generate the mesh only where the equation provides valid results. I wrote a quick script to do that below. It's incomplete as it only calculates vertices coordinates (result in the image above), and does not generate edges and faces, but it's a start:

import bpy, bmesh
import numpy     as np
from   math      import sqrt
from   itertools import product

# Define X and Y values lower bound, upper bound and number of points
lb, ub, n = ( -30, 30, 1000 )

# Calculate all the possible X-Y combinations and convert to a numpy array
xy = np.array( list( product( np.linspace( lb, ub, n ), np.linspace( lb, ub, n ) ) ) )

# Split X and Y to different arrays and initialize Z array
xs = xy[:,0]
ys = xy[:,1]
zs = []

# Iterate over every x and y value, and try to calculate the z.
# Append result if successful, and nan if not
for x, y in zip( xs, ys ):
try:
zs.append(
(
sqrt(
-16 * abs(x) + 40 * sqrt( abs(x) ) * y - 16 * pow( x, 2 ) - 25 * pow( y, 2 ) + 16
) + 15 * x
) / 15
)
except:
zs.append( np.nan )

# Drop nan values from all axes
zs = np.array( zs )[ mask ]

# Generate mesh
bm = bmesh.new()