This is a small post in which I want to explain how to transform a smooth cubic Bézier curve (S) into a cubic Bézier (C). This may be useful if you want to tackle SVG morphing.

In code a smooth cubic Bézier is always preceded by another cubic Bézier or another smooth cubic Bézier curve, and looks like this:

<path d="M10,95
C25,15 75,10 125,95
S225,185 240,95" />

The code for the smooth cubic Bézier begins with the command S. The first pair of values (225,185) represents the second control point of the curve, and the second pair of values (240,95) represents the ending point. The first control point is calculated as a reflection of the second control point (75,10) of the previous curve (C25,15 75,10 125,95).

reflected_x = (2*joiningPoint.x - cp2.x);
reflected_y = (2*joiningPoint.y - cp2.y);

I've putted all this in a function.
The function takes 2 arguments: The first argument is the previous command splitted into an array. In the example above previous = ["C",25,15, 75,10, 125,95];

The second argument is the smooth cubic Bézier command, also splitted into an array. In the example above command = ["S",225,185, 240,95];

function S2C_helper(previous,command){
// previous = ["C",25,15, 75,10, 125,95]
// command = ["S",225,185,240,95]
let x2 = Number((previous[previous.length - 4]));//cp2 x
let y2 = Number((previous[previous.length - 3]));//cp2 y
let x3 = Number((previous[previous.length - 2]));//joining point x
let y3 = Number((previous[previous.length - 1]));//joining point y

///////////////////////////////////////
// the reflected control point
let reflected_x = (2*x3 - x2);
let reflected_y = (2*y3 - y2);
///////////////////////////////////////

return ["C",reflected_x,reflected_y,command,command,command,command]
}

The function returns an array containing the information required to code a cubic Bézier curve. In this example the returned value is ["C", 175, 180, 225, 185, 240, 95] This translated in SVG looks like this:

<path d="M10,95
C25,15 75,10 125,95
C175,180 225,185 240,95" />

2,153 0 8