Exemplo n.º 1
0
def textObj(text,
            textType,
            textPos,
            textRot,
            textScale=(0.75, 0.75, 0.75),
            numberMaterial=(1, 1, 1, 1)):
    """
    The function creates font objects and convert it into meshes.
    Arguments:
        text            : The text to written in the Viewport.
        textType        : The name to be used in object Collection.
        textPos         : The position of object in the Viewport.
        textRot         : The rotation of object in the Viewport.
        textScale       : The scaling of object in the ViewPort. Default value is (0.75,0.75,0.75).
        numberMaterial  : The material color of numbers. Default value gives White.  
    """

    font_curve = bpy.data.curves.new(type="FONT", name="Font Curve")
    font_curve.body = str(text)
    font_obj = bpy.data.objects.new(textType + " " + str(text), font_curve)
    bpy.context.scene.collection.objects.link(font_obj)
    bpy.data.objects[textType + " " + str(text)].select_set(True)
    bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS', center='MEDIAN')
    font_obj.location = textPos
    font_obj.rotation_euler = textRot
    font_obj.scale = textScale
    bpy.context.view_layer.objects.active = font_obj
    bpy.context.active_object.select_set(True)
    bpy.ops.object.convert(target="MESH")
    createMaterial("NumberMaterial", numberMaterial)
    return
Exemplo n.º 2
0
def scatterPlot2D(X, y, cat, gridMaterial, numberMaterial):
    """
    ==============
    SCATTERPLOT 2D
    ==============
    A scatterplot in two dimenshion is used to display the relationship between two quantitative variables.
    Arguments :
        X               : The array of quantitative values passed by user. It must be of number data type.
        y               : The array of quantitative values passed by user. It must be of number data type.
        cat             : The array of categorical values respected to each value in (X, y).  
        gridMaterial    : The material color for grid in plot. Default color is White.
        numberMaterial  : The material color for numbers in plot. Default color is White.
    Imported User Defined Functions :
        clearScreen     : It will delete everything on the Blender Viewport .
        textObj         : It will create a text object and convert into meshes.
        transform       : This will be used as move function for objects.
        createMaterial  : The materials were created and assigned if not exist.
    """

    # 8 colors are declared right now for to use, every material is diffuse material in Blender
    scatterMaterial = [("red", (1, 0, 0, 1)), ("yellow", (1, 1, 0, 1)),
                       ("blue", (0, 0, 1, 1)), ("green", (0, 1, 0, 1)),
                       ("cyan", (0, 1, 1, 1)), ("purple", (1, 0, 1, 1)),
                       ("magenda", (1, 0, 0.25, 1), ("orange", (1, 0.25, 0,
                                                                1)))]

    # Delete everything on the screen.
    clearScreen()

    # Variables used in the function.
    X_y_cat = []
    X_y_cat.extend([list(a) for a in zip(X, y, cat)])
    y_maxVal = max(y)
    X_maxVal = max(X)
    X_scale = math.ceil(X_maxVal / 10)
    y_scale = math.ceil(y_maxVal / 10)
    total = len(X)
    categories = list(set(cat))

    # Adding 2D grid
    create2DGrid(gridName="X_Y",
                 gridSize=10,
                 gridLoc=(0, 0, 0),
                 gridRot=(math.radians(0), math.radians(-90), math.radians(0)),
                 x_sub=11,
                 y_sub=11,
                 gridMaterial=gridMaterial)

    # Numbering X-axis and y-axis
    for num in range(11):
        textObj(text=int(num * y_scale),
                textType="y_plot",
                textPos=(0, -1, num),
                textRot=(math.radians(90), math.radians(0), math.radians(90)),
                textScale=(0.4, 0.4, 0.4),
                numberMaterial=numberMaterial)
        textObj(text=int(num * X_scale),
                textType="X_plot",
                textPos=(0, num, -1),
                textRot=(math.radians(90), math.radians(0), math.radians(90)),
                textScale=(0.4, 0.4, 0.4),
                numberMaterial=numberMaterial)

    # Adding a sphere in the corresponding cartesian position.
    for i in range(len(categories)):
        for itr in range(total):
            if categories[i] == X_y_cat[itr][-1]:
                # Creating a sphere.
                bpy.ops.mesh.primitive_uv_sphere_add(
                    segments=6,
                    ring_count=6,
                    radius=0.12,
                    enter_editmode=False,
                    align='WORLD',
                    location=(0, X[itr] / X_scale, y[itr] / y_scale))
                # The Name will be in the format : "Scatter No: 0, Cat: Male"
                bpy.context.active_object.name = "Scatter No:" + str(
                    itr) + ", Cat :" + str(categories[i])
                # The material will be created and applied.
                createMaterial(materialName="ScatterMaterial :" +
                               str(categories[i]),
                               diffuseColor=scatterMaterial[i][1])
                mesh = bpy.context.object.data
                for f in mesh.polygons:
                    f.use_smooth = True

    bpy.ops.object.select_all(action='DESELECT')
    return
Exemplo n.º 3
0
def barPlot(X, y, gridMaterial, barMaterial, numberMaterial):
    """
    =======
    BARPLOT
    =======
    A barplot shows the relationship between a numeric and a categoric variable. 
    Each entity of the categoric variable is represented as a bar. 
    The size of the bar represents its numeric value. 
    Arguments :
        X               : The array of values passed by user. It must be of number data type.
        y               : The array of values passed by user. It must be categoric variable respected to X array.
        gridMaterial    : The material color for grid in plot. Default color is White.
        numberMaterial  : The material color for numbers in plot. Default color is White.
        barMaterial     : The material color for bars in plot. Default color is Red.
    Imported User Defined Functions :
        clearScreen     : It will delete everything on the Blender Viewport .
        textObj         : It will create a text object and convert into meshes.
        transform       : This will be used as move function for objects.
        createMaterial  : The materials were created and assigned if not exist.
    """
    # Delete everything on the screen.
    clearScreen()

    # Variables used in the function.
    maxVal = max(y)
    total = len(X)
    X_scale = 10 / total
    y_scale = math.ceil(maxVal / 10)
    size_bar = 1
    cursor = size_bar / 2

    # 0.01 is added in the Location is to prevent face mix.
    create2DGrid(gridName="X_Y",
                 gridSize=10,
                 gridLoc=(-(size_bar / 2) + 0.01, 0, 0),
                 gridRot=(math.radians(0), math.radians(-90), math.radians(0)),
                 x_sub=11,
                 y_sub=2,
                 gridMaterial=gridMaterial)

    # Y axis will be numbered.
    for num in range(11):
        textObj(text=num * y_scale,
                textType="y_plot",
                textPos=(-(size_bar / 2), -1, num),
                textRot=(math.radians(90), math.radians(0), math.radians(90)),
                numberMaterial=numberMaterial)

    # X axis will be numbered and graph will be plotted.
    for itr in range(total):
        # Create a plane and extruded to a bar.
        bpy.ops.mesh.primitive_plane_add(size=size_bar,
                                         enter_editmode=False,
                                         location=(0, cursor, 0))
        bpy.context.active_object.name = "Bar " + str(X[itr])
        # The material will be created and applied.
        createMaterial(materialName="BarMaterial", diffuseColor=barMaterial)

        # Scaling bar plots in X axis.
        transform(mode='EDIT',
                  type='EDGE',
                  size_bar=size_bar,
                  X_scale=X_scale,
                  indices=[2,
                           3])  #[2,3] reps rhs of plane from user perspective

        # Extruding plane in Z-axis to make into bar.
        bpy.ops.object.mode_set(mode='EDIT')
        bpy.ops.mesh.select_mode(type='FACE')
        bpy.ops.mesh.select_all(action='SELECT')
        bpy.ops.mesh.extrude_region_move(
            TRANSFORM_OT_translate={"value": (0, 0, y[itr] / y_scale)})
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS',
                                  center='MEDIAN')
        textObj(text=X[itr],
                textType="X_plot",
                textPos=(0, (X_scale - size_bar) / 2 + cursor, -1),
                textRot=(math.radians(90), math.radians(90), math.radians(90)),
                textScale=(min(1, X_scale), min(1, X_scale), min(1, X_scale)),
                numberMaterial=numberMaterial)
        cursor += X_scale

    bpy.ops.object.select_all(action='DESELECT')
    return
Exemplo n.º 4
0
def histPlot(X, gridMaterial, numberMaterial, bins=None, cat=None):
    """
    ========
    HISTPLOT
    ========
    A histPlot is a graphical representation that organizes a group of data points into user-specified ranges.
    Arguments :
        X               : The array of values passed by user. It must be of number data type.
        gridMaterial    : The material color for grid in plot. Default color is White.
        numberMaterial  : The material color for numbers in plot. Default color is White.
        bins            : The class interval for blocking the data values. Default value is calculated by the equation [maxVal-minVal]/sqrt(len(X))].
        cat             : The array of categorical values respected to each value in array X.  
    Imported User Defined Functions :
        clearScreen     : It will delete everything on the Blender Viewport .
        textObj         : It will create a text object and convert into meshes.
        transform       : This will be used as move function for objects.
        createMaterial  : The materials were created and assigned if not exist.
    """

    # 8 colors are declared right now for to use, every material is diffuse material in Blender
    barMaterial = [
        ("red",(1,0,0,1)),("yellow",(1,1,0,1)),("blue",(0,0,1,1)),
        ("green",(0,1,0,1)),("cyan",(0,1,1,1)),("purple",(1,0,1,1)),
        ("magenda",(1,0,0.25,1),("orange",(1,0.25,0,1)))
    ]

    # Delete everything on the screen.
    clearScreen()

    # Variables used in the function.
    X_cat = []
    X_cat.extend([list(a) for a in zip(X, cat)])
    X_cat.sort(key=lambda x: x[0])
    maxVal = X_cat[-1][0]
    minVal = X_cat[0][0]
    if bins is None:
        values = math.ceil(math.sqrt(len(X_cat)))
        bins = math.ceil((maxVal-minVal)/values)
    y_new = []
    size_bar = 1
    y_cat = []
    y_cursor = size_bar/2
    X_new = list(range(math.ceil(minVal-1),math.ceil(maxVal),bins))
    current = bins
    categories = list(set(cat))
    y_cursor = size_bar/2

    # Divide and calculate the heights of plots respect to bins.
    for category in categories:
        y_new = []
        hist = 0
        current = bins
        hist = 0
        count = 0
        while count < len(X_cat):
            if X_cat[count][0] <= current:
                if X_cat[count][1] == category:
                    hist += 1
                count += 1
            else:
                y_new.append(hist)
                current += bins
                hist = 0
        y_new.append(hist)
        y_cat.append(y_new)
    y_scale = math.ceil(maxVal/10)
    X_scale = 10/len(X_new)

    # 0.01 is added in the Location is to prevent face mix.
    create2DGrid(
        gridName="X-Y", gridSize=10, gridLoc=(-(size_bar/2)+0.01, 0, 0),
        gridRot=(math.radians(0), math.radians(-90), math.radians(0)),
        x_sub=11, y_sub=2, gridMaterial=gridMaterial
    )

    # Y axis will be numbered.
    for num in range(11):    
        textObj(
            text=num*y_scale, textType="y_plot", 
            textPos=(-(size_bar/2), -1, num), textRot=(math.radians(90),math.radians(0) ,math.radians(90)),
            numberMaterial=numberMaterial
        )        

    # X axis will be numbered and graph will be plotted.
    for itr in range(len(X_new)):
        z_cursor = 0
        for i in range(len(categories)):
            # To check category value exists in the corresponding bins or not.
            if y_cat[i][itr] == 0:
                continue

            # Create a plane and extruded to a bar.
            bpy.ops.mesh.primitive_plane_add(size=size_bar, enter_editmode=False, location=(0, y_cursor, z_cursor))
            # The Bar name will be in the format of : "Bar No: 0, Cat: Male, Count: 6"
            bpy.context.active_object.name = "Bar No: " + str(X_new[itr]) + ", Cat: " + str(categories[i]) + ", Count: " + str(y_cat[i][itr])
            # The material will be created and applied.
            createMaterial(
                materialName="BarMaterial "+ str(categories[i]), diffuseColor=barMaterial[i][1]
            )
        
            # Scaling bar plots in X axis.
            transform(
                mode='EDIT', type='EDGE', size_bar=size_bar, 
                X_scale=X_scale, indices=[2,3]      #[2,3] represents RHS of plane from user perspective.
            )
        
            # Extruding plane in Z-axis to make into bar.
            bpy.ops.object.mode_set(mode = 'EDIT')
            bpy.ops.mesh.select_mode(type = 'FACE')
            bpy.ops.mesh.select_all(action = 'SELECT')
            bpy.ops.mesh.extrude_region_move(
                TRANSFORM_OT_translate={"value":(0, 0, (y_cat[i][itr]/y_scale))}
            )
            z_cursor += (y_cat[i][itr]/y_scale)
            bpy.ops.object.mode_set( mode = 'OBJECT' )
            bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS', center='MEDIAN')
        y_cursor += X_scale
        textObj(
            text=X_new[itr], textType="X_plot", 
            textPos=(0, X_scale*itr, -1), textRot=(math.radians(90),math.radians(0),math.radians(90)),
            textScale=(min(1,X_scale/1.5), min(1,X_scale/1.5), min(1,X_scale/1.5)),
            numberMaterial=numberMaterial
        ) 
    # To plot the last number of X axis
    textObj(
        text=max(X_new)+bins, textType="X_plot", 
        textPos=(0, 10, -1), textRot=(math.radians(90),math.radians(0),math.radians(90)),
        textScale=(min(1,X_scale/1.5), min(1,X_scale/1.5), min(1,X_scale/1.5)), 
        numberMaterial=numberMaterial
    )    
    bpy.ops.object.select_all(action = 'DESELECT')
    return
Exemplo n.º 5
0
def create2DGrid(gridName,
                 gridSize,
                 gridLoc,
                 gridRot,
                 x_sub,
                 y_sub,
                 gridMaterial=(1, 1, 1, 1)):
    """
    Create a Grid of provided size. It will be of square of size provided in gridSize.
    Arguments:
        gridName        : The name of grid.
        gridSize        : The size of grid.
        gridLoc         : The global position of grid.
        x_sub           : The subdivisions in X axis.
        y_sub           : The subdivisions in y axis.
        gridMaterial    : The material color of grid. Default value gives White diffuse material
    Imported User Defined Functions :
        createMaterial  : The materials were created and assigned if not exist.
    """

    bpy.ops.mesh.primitive_grid_add(size=gridSize,
                                    location=gridLoc,
                                    rotation=gridRot,
                                    x_subdivisions=x_sub,
                                    y_subdivisions=y_sub)
    bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
    bpy.context.active_object.name = "Grid " + gridName
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='DESELECT')
    obj = bpy.context.edit_object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    bm.faces.active = None

    # Changing origin to origin of plot.
    for v in bm.verts:
        if v.index == 0:
            v.select = True
            co = v.co
            bpy.context.scene.cursor.location = (co.x, co.y, co.z)
            bpy.ops.object.mode_set(mode='OBJECT')
            bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
            break
    if co.y == co.z:
        bpy.ops.transform.translate(value=(0, 0 - co.y, 0 - co.z),
                                    orient_type='GLOBAL',
                                    orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0,
                                                                          1)))
    elif co.x == co.y:
        bpy.ops.transform.translate(value=(0 - co.x, 0 - co.y, 0),
                                    orient_type='GLOBAL',
                                    orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0,
                                                                          1)))
    elif co.x == co.z:
        bpy.ops.transform.translate(value=(0 - co.x, 0, 0 - co.z),
                                    orient_type='GLOBAL',
                                    orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0,
                                                                          1)))

    # Adding wireframe modifier to get grid structure.
    bpy.ops.object.modifier_add(type='WIREFRAME')
    bpy.context.object.modifiers["Wireframe"].thickness = 0.05
    createMaterial("GridMaterial", gridMaterial)
    return
Exemplo n.º 6
0
def surfacePlot(z, gridMaterial, surfaceMaterial, numberMaterial):
    """
    ===========
    SURFACEPLOT
    ==========
    Surface plots are diagrams of three-dimensional data. 
    It shows a functional relationship between a designated dependent variable (z), and two independent variables (X and y).
    Arguments :
        z                   : The m*n array of values passed by user. It must be of number data type.
        gridMaterial        : The material color for grid in plot. Default color is White.
        numberMaterial      : The material color for numbers in plot. Default color is White.
        surfaceMaterial     : The material color for surface in plot. Default color is Red.
    Imported User Defined Functions :
        clearScreen         : It will delete everything on the Blender Viewport .
        textObj             : It will create a text object and convert into meshes.
        transform           : This will be used as move function for objects.
        createMaterial      : The materials were created and assigned if not exist.
    """
    # To delete default objects
    clearScreen()

    # Variables used in the function.
    # X and y are obtained from length of 2D array.
    X = len(z[0])
    y = len(z)
    z_maxVal = max(list(map(max, z)))
    z_scale = math.ceil(z_maxVal / 10)
    X_scale = math.ceil(X / 10)
    y_scale = math.ceil(y / 10)

    # Adding 3 2D grids for 3D space.
    create2DGrid(gridName="Y_Z",
                 gridSize=10,
                 gridLoc=(0, 0, 0),
                 gridRot=(math.radians(0), math.radians(-90), math.radians(0)),
                 x_sub=11,
                 y_sub=11,
                 gridMaterial=gridMaterial)
    create2DGrid(gridName="X_Y",
                 gridSize=10,
                 gridLoc=(0, 0, 0),
                 gridRot=(math.radians(0), math.radians(0), math.radians(0)),
                 x_sub=11,
                 y_sub=11,
                 gridMaterial=gridMaterial)
    create2DGrid(gridName="Z_X",
                 gridSize=10,
                 gridLoc=(0, 0, 0),
                 gridRot=(math.radians(90), math.radians(0), math.radians(0)),
                 x_sub=11,
                 y_sub=11,
                 gridMaterial=gridMaterial)

    # Numbering X-axis, y-axis and z-axis.
    for num in range(X // X_scale):
        textObj(text=int(num * X_scale),
                textType="X_plot",
                textPos=((10 / (X - 1)) * num * X_scale, -1, 0),
                textRot=(math.radians(0), math.radians(0), math.radians(90)),
                textScale=(0.4, 0.4, 0.4),
                numberMaterial=numberMaterial)
    for num in range(y // y_scale):
        textObj(text=int(num * y_scale),
                textType="y_plot",
                textPos=(0, (10 / (y - 1)) * num * y_scale, -1),
                textRot=(math.radians(90), math.radians(0), math.radians(90)),
                textScale=(0.4, 0.4, 0.4),
                numberMaterial=numberMaterial)
    for num in range(11):
        textObj(text=int(num * z_scale),
                textType="z_plot",
                textPos=(0, -1, num),
                textRot=(math.radians(90), math.radians(0), math.radians(90)),
                textScale=(0.4, 0.4, 0.4),
                numberMaterial=numberMaterial)

    # Adding grid as surface.
    bpy.ops.mesh.primitive_grid_add(size=10,
                                    location=(5, 5, 0),
                                    x_subdivisions=X,
                                    y_subdivisions=y)
    bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
    createMaterial(materialName="SurfaceMaterial",
                   diffuseColor=surfaceMaterial)
    bpy.context.active_object.name = "Surface"
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='DESELECT')
    obj = bpy.context.edit_object
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    bm.faces.active = None

    # Plotting the values by moving grid vertices in given z axis.
    # First, make z in a single list.
    flat_z = [item for sublist in z for item in sublist]
    z_count = 0

    # Moving each vertex in Z axis.
    for v in bm.verts:
        v.select = True
        bpy.ops.transform.translate(value=(0, 0, flat_z[z_count] / z_scale),
                                    orient_type='GLOBAL',
                                    orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0,
                                                                          1)))
        z_count += 1
        v.select = False

    bpy.ops.mesh.select_all(action='DESELECT')
    bpy.ops.object.mode_set(mode='OBJECT')
    return