0

Now the method I'm using can only get the points of one curve, because the second curve I don't know the start point,I tried to use the end point of the first curve to be the start point of the second curve, but it seems to be wrong,Ive tried multiple variations of this, but none of them seem to work. Any ideas? here is my curves,I saved them in an array:

["M 326, 184 C326, 184",
"341, 197 426, 204 514, 210",
"643, 205 676, 184 677, 192",
"647, 251 674, 251 674, 251",
"666, 420 666, 420 666, 420",
"649, 815 647, 846 631, 877",
"557, 900 500, 898 450, 901",
"373, 877 355, 846 353, 798",
"346, 642 346, 642 346, 642 325, 228 326, 184 Z"]
var PI2=Math.PI*2;
var s={x:dis[i][0],y:dis[i][1]};
var c1={x:dis[i][2],y:dis[i][3]};
var c2={x:dis[i][4],y:dis[i][5]};
var e={x:dis[i][6],y:dis[i][7]};
// an array of points plotted along the bezier curve


// we use PI often so put it in a variable
var PI=Math.PI;

// plot 400 points along the curve
// and also calculate the angle of the curve at that point
// NOTE: You may need to adjust the point count (==100 here)
//      if the curve is much shorter or longer than this demo's curve
for(var t=0;t<=100;t+=0.25){

  var T=t/100;

  // plot a point on the curve
  var pos=getCubicBezierXYatT(s,c1,c2,e,T);

  // calculate the tangent angle of the curve at that point
  
  var tx = bezierTangent(s.x,c1.x,c2.x,e.x,T);
  var ty = bezierTangent(s.y,c1.y,c2.y,e.y,T);
  var a = Math.atan2(ty, tx)-PI/2;

  // save the x/y position of the point and the tangent angle
  // in the points array
  points.push({
    x:pos.x,
    y:pos.y,
    angle:a
  });
}
}

function getCubicBezierXYatT(startPt,controlPt1,controlPt2,endPt,T){
  var x=CubicN(T,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
  var y=CubicN(T,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
  return({x:x,y:y});
}

// cubic helper formula at T distance
function CubicN(T, a,b,c,d){
  var t2 = T * T;
  var t3 = t2 * T;
  return a + (-a * 3 + T * (3 * a - a * T)) * T
  + (3 * b + T * (-6 * b + b * 3 * T)) * T
  + (c * 3 - c * 3 * T) * t2
  + d * t3;
}

// calculate the tangent angle at interval T on the curve
function bezierTangent(a, b, c, d, t){
  return (3 * t * t * (-a + 3 * b - 3 * c + d) + 6 * t * (a - 2 * b + c) + 3 * (-a + b));
 
};```
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
  • What do you mean with "because the second curve I don't know the start point"? You're using SVG `C` sequences with absolute coordinates, so the start point of the second curve is simply the end point of the first curve. `(426, 204)` in this case. On which note: `C` takes three coordinate pairs, for c1, c2, and end point, so the way you've split up your string into your array is going to confuse you. If you have to split it over multiple lines, split it as `"C 326 184 341 197 426 204", "514 210 643 205 676 184", ...` – Mike 'Pomax' Kamermans Jan 10 '22 at 18:35
  • And on a JS note, you seem to be using pretty legacy notation. You can get Math functions out as their own thing by using `const { atan2, PI } = Math;`, and you don't want to use `var`: use `let` and `const` (depending on whether the variable should be reassignable), because unlike `var`, those are propely block scoped (your looping var `t`, for instance, doesn't exist "only inside your for loop", because you used `var` it gets hoisted to where it's defined throughout the _entire_ script. From the very first line even) – Mike 'Pomax' Kamermans Jan 10 '22 at 18:45
  • Can I split it this way to get control points? "c 326 184 326 184 341 197 426 204," "c 426,204,(End point of the first curve),514,210,643 205 676 184" – staccoverflow Jan 11 '22 at 03:30
  • That split up string is an SVG path string (specifically, [the `d` attribute](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d)), and the placement of `C` is basically fixed. `C` is a function, and it takes (multiples of) 6 arguments. The first two are the first control point, the second two the second control point, and the third two are the end point. – Mike 'Pomax' Kamermans Jan 11 '22 at 15:10

0 Answers0