Optical_flow_lover
Optical_flow_lover

Reputation: 129

Fill area of regions of two intersecting lines

I have two lines:

y=3x-4 
y=-x+5

They intersect and form 4 regions in space (see image below).

enter image description here

Mathematically, the regions can be determined with the following inequations:

Region1: y<3x-4 & y>-x+5
Region2: y>3x-4 & y>-x+5
Region3: y>3x-4 & y<-x+5
Region4: y<3x-4 & y<-x+5

I want to fill all of those regions independently. However when I try to use plt.fill_between I can only get regions 1 and/or 3. How can I fill regions 2 and 4 using matplotlib and fill_between?

The code that I tried for region 3 is the following (source):

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0,6,0.1)
y = np.arange(0,6,0.1)

# The lines to plot
y1 = 3*x - 4
y2 = -x+5

# The upper edge of polygon (min of lines y1 & y2)
y3 = np.minimum(y1, y2)

# Set y-limit, making neg y-values not show in plot
plt.ylim(0, 6)
plt.xlim(0, 6)

# Plotting of lines
plt.plot(x, y1,
         x, y2)

# Filling between (region 3)
plt.fill_between(x, y2, y3, color='grey', alpha=0.5)
plt.show()

enter image description here

Upvotes: 1

Views: 443

Answers (2)

Yulia V
Yulia V

Reputation: 3559

It's because you have set the limits incorrectly. Setting them as 2 horizontal lines, 6 and 0, does the trick. Note that I have changed the step of arange because, to have a neat picture, the intersection point (2.25 in your case) needs to belong to x range

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0,6,0.05)

# The lines to plot
y1 = 3*x - 4
y2 = -x+5

# Set y-limit, making neg y-values not show in plot
plt.ylim(0, 6)
plt.xlim(0, 6)

# Filling between (region 3)
plt.fill_between(x, np.maximum(y1, y2), [6] * len(x), color='grey', alpha=0.5)
plt.fill_between(x, np.minimum(y1, y2), [0] * len(x), color='cyan', alpha=0.5)
plt.show()

enter image description here

Upvotes: 2

Joseph Farah
Joseph Farah

Reputation: 2534

The trick here is to define a new polygon based on the intersections of the lines, and use $y(x) = 0$ as your bottom border.

The implementation of this requires the following code. First we externally calculate and hardcode the intersection points between the lines and the a-axis:

# calculate intersections between lines and x axis
intersect_x = 9/4
y1_0 = 4/3
y2_0 = 5

Once we have those stored, we go through every x value. If the x value is greater than our starting point (where the climbing curve crosses the x-axis) but less than the intersection point, we add the climbing curve point at that x value. If the x-value is greater than the intersection point but less than the end point (where the falling curve crosses the x-axis), we add the falling curve point at that x value. At each step, we add a y=0 point to a new list to be our floor for the fill-in operation.

# here we manually perform the operation you were trying to do
# with np.minimum; we also add an (x, 0) point for 
# every point we add to our new polygon
new_x = []
new_y = []
bottom_y = []
for x_dx, xx in enumerate(x):
    if xx > y1_0 and xx < intersect_x: 
        new_x.append(xx)
        new_y.append(y1[x_dx])
        bottom_y.append(0)
    elif xx < y2_0 and xx > intersect_x:
        new_x.append(xx)
        new_y.append(y2[x_dx])
        bottom_y.append(0)

Now we just replace our fill_between code with the new curves:

plt.fill_between(new_x, new_y, bottom_y, color='grey', alpha=0.5)

This is the full code:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0,6,0.1)
y = np.arange(0,6,0.1)

# The lines to plot
y1 = 3*x - 4
y2 = -x+5

# calculate intersections between lines and x axis
intersect_x = 9/4
y1_0 = 4/3
y2_0 = 5

# here we manually perform the operation you were trying to do
# with np.minimum; we also add an (x, 0) point for 
# every point we add to our new polygon
new_x = []
new_y = []
bottom_y = []
for x_dx, xx in enumerate(x):
    if xx > y1_0 and xx < intersect_x: 
        new_x.append(xx)
        new_y.append(y1[x_dx])
        bottom_y.append(0)
    elif xx < y2_0 and xx > intersect_x:
        new_x.append(xx)
        new_y.append(y2[x_dx])
        bottom_y.append(0)


# The upper edge of polygon (min of lines y1 & y2)
y3 = np.minimum(y1, y2)


# Set y-limit, making neg y-values not show in plot
plt.ylim(0, 6)
plt.xlim(0, 6)

# Plotting of lines
plt.plot(x, y1,
         x, y2)

# Filling between (region 3)
plt.fill_between(new_x, new_y, bottom_y, color='grey', alpha=0.5)
plt.show()

And this is the result:

enter image description here

Happy coding!

Upvotes: 1

Related Questions