Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to color voronoi according to a color scale ? And the area of each cell

Is it possible to color the scipy.spatial.Voronoi diagram? I know it is.

But now my goal is to color each cell according to a color scale to represent a physical quantity.

As in the image below (PRL 107, 155704 (2011)):

enter image description here

And I would also like to know if it is possible to calculate the area of each cell, because it is a quantity that I would like to calculate

like image 717
altarbza Avatar asked Dec 20 '16 14:12

altarbza


People also ask

What is Voronoi method?

Voronoi is a method to make a partition of a plane into regions close to each of a given set of objects. Imagine we have a plane and there are some points on the plane, Voronoi's objective is to make regions where every region is closer to a particular point than the other points.

Why are some of my Voronoi regions not colored?

As you can see some of the Voronoi regions at the border of the image are not colored. That is because some indices to the Voronoi vertices for these regions are set to -1, i.e., for those vertices outside the Voronoi diagram. According to the docs:

Why are the Voronoi indices set to-1 for these regions?

That is because some indices to the Voronoi vertices for these regions are set to -1, i.e., for those vertices outside the Voronoi diagram. According to the docs:

How do I select the right color scale for my data?

As you hover your cursor over each one, you can see the arrangement of the colors in a screen tip. Plus, you’ll see the cells that you’ve selected highlighted with each option. This gives you a terrific way to select the color scale that best fits your data.

How to format cells with colours in Excel?

In the New Formatting Rule box, select Format only cells that contain under Select a Rule Type. In the Rule Description choose the condition greater than or equal to and put in the value 20. Now, click on the Format to fill in the cell with colors. For this, go to the Fill tab in the Format Cells box and pick a background color.


1 Answers

Color scale:

Actually the link you provide gives the code needed to colorize the Voronoi diagram. In order to assign each cell a color representing a physical quantity, you need to map the values of this physical quantity to a normalized colormap using the method shown in Map values to colors in matplotlib.

For example, if I want to assign each cell a color corresponding to a quantity 'speed':

import numpy as np
import matplotlib as mpl
import matplotlib.cm as cm
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi, voronoi_plot_2d

# generate data/speed values
points = np.random.uniform(size=[50, 2])
speed = np.random.uniform(low=0.0, high=5.0, size=50)

# generate Voronoi tessellation
vor = Voronoi(points)

# find min/max values for normalization
minima = min(speed)
maxima = max(speed)

# normalize chosen colormap
norm = mpl.colors.Normalize(vmin=minima, vmax=maxima, clip=True)
mapper = cm.ScalarMappable(norm=norm, cmap=cm.Blues_r)

# plot Voronoi diagram, and fill finite regions with color mapped from speed value
voronoi_plot_2d(vor, show_points=True, show_vertices=False, s=1)
for r in range(len(vor.point_region)):
    region = vor.regions[vor.point_region[r]]
    if not -1 in region:
        polygon = [vor.vertices[i] for i in region]
        plt.fill(*zip(*polygon), color=mapper.to_rgba(speed[r]))
plt.show()

Sample output:

(Voronoi diagram))

Area of cells:

scipy.spatial.Voronoi allows you to access the vertices of each cell, which you can order and apply the shoelace formula. I haven't tested the outputs enough to know if the vertices given by the Voronoi algorithm come already ordered. But if not, you can use the dot product to get the angles between the vector to each vertex and some reference vector, and then order the vertices using these angles:

# ordering vertices
x_plus = np.array([1, 0]) # unit vector in i direction to measure angles from
    theta = np.zeros(len(vertices))
    for v_i in range(len(vertices)):
        ri = vertices[v_i]
        if ri[1]-self.r[1] >= 0: # angle from 0 to pi
            cosine = np.dot(ri-self.r, x_plus)/np.linalg.norm(ri-self.r)
            theta[v_i] = np.arccos(cosine)
        else: # angle from pi to 2pi
            cosine = np.dot(ri-self.r, x_plus)/np.linalg.norm(ri-self.r)
            theta[v_i] = 2*np.pi - np.arccos(cosine)

    order = np.argsort(theta) # returns array of indices that give sorted order of theta
    vertices_ordered = np.zeros(vertices.shape)
    for o_i in range(len(order)):
        vertices_ordered[o_i] = vertices[order[o_i]]

# compute the area of cell using ordered vertices (shoelace formula)
partial_sum = 0
for i in range(len(vertices_ordered)-1):
    partial_sum += vertices_ordered[i,0]*vertices_ordered[i+1,1] - vertices_ordered[i+1,0]*vertices_ordered[i,1]
    partial_sum += vertices_ordered[-1,0]*vertices_ordered[0,1] - vertices_ordered[0,0]*vertices_ordered[-1,1]
area = 0.5 * abs(partial_sum)
like image 98
The Hagen Avatar answered Sep 21 '22 06:09

The Hagen