Extend the line to seamlessly connect to another line

I have two curves that look like this:

fig1

I am looking for a way to smoothly connect a blue curve to a red one, expanding the first (blue line) up and to the right , leaving the last (red line) untouched.The direction is important, I mention this because it seems like it would be easier to continue the blue line on the left. I cannot do this (this does not make sense in my larger code), so it should be up and to the right.

Here is what I managed to do so far (the area where the two lines are approaching has been increased):

fig2

Basically, I interpolate the new curve using a sample of points from both curves (black points). The MWE code to get this graph is below.

Now I need to find a way to crop the green line from the point where it corresponds to the red line, to the point where it meets the blue line, and extend the blue line, replacing the last small segment, which is now no longer needed.

This is how the blue line should follow the changes made (done manually):

fig3

where the cropped section of the green line is now part of the blue line. Please note that I have:

  • discarded additional points of the green line that go beyond the intersection with the red line
  • discarded additional points of the green line that go beyond the intersection with the blue line.
  • attached the remainder of the green line to the blue line after discarding part of the blue line that extended to the left behind the intersection of green and blue lines.

Since I already have an interpolation curve (green line), all I need is a way:

  • Trim it to the points where it intersects the other two curves, as described above.
  • Replace the last part of the blue line with this cut off part of the new interpolated line.

In this specific example, I used fixed lists to build and perform calculations, but I have several pairs of lines for which I need to perform a similar operation, so the solution should be general enough to consider cases with similar shapes, but different curves. How can i do this?

I am open to solutions using numpy , scipy or whatever is needed.

Here's the MWE :

 import numpy as np import matplotlib.pyplot as plt # Red line data. x1 = [0.01, 0.04, 0.08, 0.11, 0.15, 0.18, 0.22, 0.25, 0.29, 0.32, 0.35, 0.38, 0.41, 0.44, 0.46, 0.49, 0.51, 0.54, 0.56, 0.58] y1 = [2.04, 2.14, 2.24, 2.34, 2.44, 2.54, 2.64, 2.74, 2.84, 2.94, 3.04, 3.14, 3.24, 3.34, 3.44, 3.54, 3.64, 3.74, 3.84, 3.94] # Blue line data. x2 = [0.4634, 0.4497, 0.4375, 0.4268, 0.4175, 0.4095, 0.4027, 0.3971, 0.3925, 0.389, 0.3865, 0.3848, 0.384, 0.3839, 0.3845, 0.3857, 0.3874, 0.3896, 0.3922, 0.3951, 0.3982, 0.4016, 0.405, 0.4085, 0.412, 0.4154, 0.4186, 0.4215, 0.4242, 0.4265, 0.4283, 0.4297, 0.4304, 0.4305, 0.4298, 0.4284, 0.4261, 0.4228, 0.4185, 0.4132, 0.4067, 0.399, 0.39, 0.3796, 0.3679, 0.3546, 0.3397, 0.3232, 0.305, 0.285] y2 = [1.0252, 1.0593, 1.0934, 1.1275, 1.1616, 1.1957, 1.2298, 1.2639, 1.298, 1.3321, 1.3662, 1.4003, 1.4344, 1.4685, 1.5026, 1.5367, 1.5708, 1.6049, 1.639, 1.6731, 1.7072, 1.7413, 1.7754, 1.8095, 1.8436, 1.8776, 1.9117, 1.9458, 1.9799, 2.014, 2.0481, 2.0822, 2.1163, 2.1504, 2.1845, 2.2186, 2.2527, 2.2868, 2.3209, 2.355, 2.3891, 2.4232, 2.4573, 2.4914, 2.5255, 2.5596, 2.5937, 2.6278, 2.6619, 2.696] x3, y3 = [], [] # Store a small section of the blue line in these new lists: only those points # closer than 0.2 to the last point in this line. for indx,y2_i in enumerate(y2): if (y2[-1]-y2_i)<=0.2: y3.append(y2_i) x3.append(x2[indx]) # The same as above but for the red line: store only those points between # 0. and 0.4 in the y axis and with a larger x value than the last point in the # blue line. for indx,y1_i in enumerate(y1): if 0. <(y1_i-y2[-1])<=0.4 and x1[indx] > x2[-1]: y3.append(y1_i) x3.append(x1[indx]) # Find interpolating curve that joins both segments stored in x3,y3. poli_order = 3 # Order of the polynome. poli = np.polyfit(y3, x3, poli_order) y_pol = np.linspace(min(y3), max(y3), 50) p = np.poly1d(poli) x_pol = [p(i) for i in y_pol] plt.plot(x1,y1, 'r') plt.plot(x2,y2, 'b') plt.plot(x_pol,y_pol, 'g') plt.scatter(x3,y3,c='k') plt.show() 
+6
source share
2 answers

As already mentioned, try using a spline. Your smooth curve in the derivative is not so smooth, the transition from a continuous line to a straight line looks like a gap in f '(x). Because of this, I tightened the borders to 0.2 from 0.4, which grab only one point for seizures of the red line. Without this, the spline will over-interpolate around additional red dots.

A quick example using your def. on top:

 from scipy.interpolate import spline sx = np.array(x2+x3) sy = np.array(y2+y3) t = np.arange(sx.size,dtype=float) t /= t[-1] N = np.linspace(0,1,2000) SX = spline(t,sx,N,order=4) SY = spline(t,sy,N,order=4) plt.plot(x1,y1, 'r') plt.plot(x2,y2, 'b') plt.scatter(x3,y3,c='k') plt.plot(SX, SY,'g',alpha=.7,lw=3) plt.show() 

enter image description here

This question is a convenient link:

Smooth spline representation of an arbitrary contour, f (length) → x, y

+2
source

You can use only 2 points on one line and two points on the other (while they are on the right side of the intersection) and use spline interpolation between them.

Or a more pleasant result (sometimes) is the use of Bezier (and now you can have more than 4 points due to the cost of increased complexity) or even NURBS . Unfortunately, this was once since I played with them, and I would not want to write code for this.

when choosing a curve, look at their properties. For example, Bezier ensures that a curve never leaves a convex polygon defined by points, so it is clearly a good candidate for what you need.

+1
source

All Articles