Home > other >  Is it possible to fill in a circular graph with a solid colour and save it as svg in matplotlib?
Is it possible to fill in a circular graph with a solid colour and save it as svg in matplotlib?

Time:02-05

I wrote some code that creates randomised patches from graphs in matplotlib. Basically how it works is that you create a graph from nodes taken from a circle using the parametric equation for a circle and then you randomly displace the nodes along the vector of (0,0) to the node point on the circumference of the circle. That way you can be certain to avoid lines from crossing each other once the circle is drawn. In the end you just append the first (x,y) coordinate to the list of coordinates to close the circle.

What I want to do next is to find a way to fill that circular graph with a solid colour so that I can create a "stamp" that can be used to make randomised patches on a canvas that hopefully will not create crossing edges. I want to use this to make procedural risk maps in svg format, because a lot of those are uploaded with terrible edges using raster image formats using jpeg.

I am pretty sure that my information of the nodes should be sufficient to make that happen but I have no idea how to implement that. Can anyone help?

import numpy as np
import matplotlib.pyplot as plt



def node_circle(r=0.5,res=100):
    # Create arrays (x and y coordinates) for the nodes on the circumference of a circle. Use parametric equation.
    # x = r cos(t)    y = r sin(t)

    t = np.linspace(0,2*np.pi,res)
    x = r*np.cos(t)
    y = r*np.sin(t)

    return t,x,y



def sgn(x,x_shift=-0.5,y_shift=1):

    # A shifted sign function to use as a switching function 
    # in order to avoid shifts lower than -0.5 which is 
    # the radius of the circle.

    return -0.5*(np.abs(x -x_shift)/(x -x_shift))  y_shift



def displacer(x,y,low=-0.5,high=0.5,maxrad=0.5):

    # Displaces the node points of the circle

    shift = 0
    shift_increment = 0

    for i in range(len(x)):
        shift_increment = np.random.uniform(low,high)
        shift  = shift_increment*sgn(maxrad)

        x[i]  = x[i]*shift
        y[i]  = y[i]*shift

    x = np.append(x,x[0])
    y = np.append(y,y[0])

    return x,y


def plot():

    # Actually visualises everything

    fig, ax = plt.subplots(figsize=(4,4))

    # np.random.seed(1)

    ax.axis('off')

    t,x,y = node_circle(res=100)

    a = 0

    x,y = displacer(x,y,low=-0.15,high=0.15)

    ax.plot(x,y,'r-')
    # ax.scatter(x,y,)

    plt.show()

plot()

CodePudding user response:

got it: the answer is to use matplotlib.Patches.Polygon

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon



def node_circle(r=0.5,res=100):
    # Create arrays (x and y coordinates) for the nodes on the circumference of a circle. Use parametric equation.
    # x = r cos(t)    y = r sin(t)

    t = np.linspace(0,2*np.pi,res)
    x = r*np.cos(t)
    y = r*np.sin(t)

    return x,y



def sgn(x,x_shift=-0.5,y_shift=1):

    # A shifted sign function to use as a switching function 
    # in order to avoid shifts lower than -0.5 which is 
    # the radius of the circle.

    return -0.5*(np.abs(x -x_shift)/(x -x_shift))  y_shift



def displacer(x,y,low=-0.5,high=0.5,maxrad=0.5):

    # Displaces the node points of the circle

    shift = 0
    shift_increment = 0

    for i in range(len(x)):
        shift_increment = np.random.uniform(low,high)
        shift  = shift_increment*sgn(maxrad)

        x[i]  = x[i]*shift
        y[i]  = y[i]*shift

    x = np.append(x,x[0])
    y = np.append(y,y[0])

    return x,y




def patch_distributor(M,N,res,grid='square'):
    
    # Distribute Patches based on a specified pattern/grid.
    
    if grid == 'square':
        data = np.zeros(shape=(M,N,2,res 1))

        for i in range(M):
            for j in range(N):
                x,y = displacer(*node_circle(res=res),low=-0.2,high=0.2)
                data[i,j,0,:] = x
                data[i,j,1,:] = y
        
        return data



def plot(res):

    # Actually visualises everything

    fig, ax = plt.subplots(figsize=(4,4))

    # np.random.seed(1)

    ax.axis('off')

    # x,y = node_circle(res=res)
    # x,y = displacer(x,y,low=-0.15,high=0.15)
    # xy = np.zeros((len(x),2))
    # xy[:,0] = x
    # xy[:,1] = y

    patch_data = patch_distributor(10,10,res)

    for i in range(patch_data.shape[0]):
        for j in range(patch_data.shape[1]):
            x,y = patch_data[i,j]
            x  = i*0.5
            y  = j*0.5
            xy = np.zeros((len(x),2))
            xy[:,0] = x
            xy[:,1] = y

            patch = Polygon(xy,fc='w',ec='k',lw=2,zorder=np.random.randint(2),antialiased=False)
            ax.add_patch(patch)

    ax.autoscale_view()

    # ax.plot(x,y,'r-')
    # ax.scatter(x,y,)

    plt.savefig('lol.png')

plot(res=40)

# Displace circle along the line of (0,0) -> (cos(t),sin(t))
# Make the previous step influence the next to avoid jaggedness
# limit displacement level to an acceptable amount
# Random displaced cubic grid as placing points for stamps.


  •  Tags:  
  • Related