贝塞尔曲线成直线 SVG 线如何转换?

问题描述

我正在努力将 SVG 曲线 C 转换为 Python 中的一组直线

语法是 C x1 y1,x2 y2,x y

这是我应该得到什么线而不是曲线的例子 https://svg-path-visualizer.netlify.app/#M%2010%2010%20C%2020%2020%2C%2040%2020%2C%2050%2010%20M%2010%2010%20L%2020%2017%20L%2040%2017%20L%2050%2010

如何用一组给定的线来近似 svg 曲线?

解决方法

//************************************************************************** // Gesture Recognizers // MARK: Gesture Recognizers //************************************************************************** @objc func handleTap(recognizer: UITapGestureRecognizer) { if(data.isNavigationOff == true) { return } // No panel select if Add,Update,EndWave,or EndGame if(gameMenuTableView.isHidden == false) { return } // No panel if game menu is showing let location: CGPoint = recognizer.location(in: gameScene) if(data.isAirStrikeModeOn == true) { let projectedPoint = gameScene.projectPoint(SCNVector3(0,0)) let scenePoint = gameScene.unprojectPoint(SCNVector3(location.x,location.y,CGFloat(projectedPoint.z))) gameControl.airStrike(position: scenePoint) } else { let hitResults = gameScene.hitTest(location,options: hitTestOptions) for vHit in hitResults { if(vHit.node.name?.prefix(5) == "Panel") { // May have selected an invalid panel or auto upgrade was on if(gameControl.selectPanel(vPanel: vHit.node.name!) == false) { return } return } } } } //************************************************************************** @objc func handlePan(recognizer: UIPanGestureRecognizer) { if(data.gameState != .run || data.isGamePaused == true) { return } currentLocation = recognizer.location(in: gameScene) switch recognizer.state { case UIGestureRecognizer.State.began: beginLocation = recognizer.location(in: gameScene) break case UIGestureRecognizer.State.changed: if(currentLocation.x > beginLocation.x * 1.1) { beginLocation.x = currentLocation.x gNodes.camera.strafeLeft() } if(currentLocation.x < beginLocation.x * 0.9) { beginLocation.x = currentLocation.x gNodes.camera.strafeRight() } break case UIGestureRecognizer.State.ended: break default: break } } 返回三次贝塞尔曲线上的一个点,其中 get_cubic_bezier_point 是曲线参数(0 到 1),t 是 4 个曲线点的列表:

p

这是一个 JS 片段来说明 CB:

import numpy as np

def get_cubic_bezier_point(t,p):
  multipliers = [
    t * t * t,3 * t * t * (1 - t),3 * t * (1 - t) * (1 - t),(1 - t) * (1 - t) * (1 - t)
  ]
  x = 0
  y = 0
  for index in range(4):
    x += p[index][0] * multipliers[index]
    y += p[index][1] * multipliers[index]
  return [x,y]

points = [
    [10,10],[100,250],[150,-100],[220,140],]  

for t in np.arange(0,1,0.1):
  point = get_cubic_bezier_point(t,points)
  print(point)
const points = [
    {x: 10,y: 10},{x: 100,y: 250},{x: 150,y: -100},{x: 220,y: 140}
];

const fp = i => `${points[i].x},${points[i].y}`;

d3.select('path').attr('d',`M ${fp(0)} C ${fp(1)} ${fp(2)} ${fp(3)}`);

const findCBPoint = t => {
    const multipliers = [
    t * t * t,(1 - t) * (1 - t) * (1 - t)
  ]
  return multipliers.reduce((s,m,i) => ({
    x: s.x + points[i].x * m,y: s.y + points[i].y * m
    }),{x: 0,y: 0});
}

for (let t = 0; t <= 1; t += 0.1) {
  const p = findCBPoint(t);
  console.log(p);
  d3.select('svg').append('circle')
    .attr('cx',p.x).attr('cy',p.y).attr('r',3);
}
path {
  stroke: red;
  fill: none;
}

,

我认为应该这样做:

function differ(no1,no2,no3,amount) {
    return no1 + ((no2 - no1) * no3 / amount);
}
function linePointOnBezier(p1,p2,p3,p4,noOfLines) {
    var t = 0;
    var points = [];
    for(var t = 0; t <= noOfLines; t++) {
        var l2 = { //layer 2
            p1: {
                x: differ(p1.x,p2.x,t,noOfLines),y: differ(p1.y,p2.y,},p2: {
                x: differ(p2.x,p3.x,y: differ(p2.y,p3.y,p3: {
                x: differ(p3.x,p4.x,y: differ(p3.y,p4.y,};
        var l3 = { //layer 3
            p1: {
                x: differ(l2.p1.x,l2.p2.x,y: differ(l2.p1.y,l2.p2.y,p2: {
                x: differ(l2.p2.x,l2.p3.x,y: differ(l2.p2.y,l2.p3.y,};
        var point = [
            differ(l3.p1.x,l3.p2.x,differ(l3.p1.y,l3.p2.y,];
        points.push(point);
    }
    return points;
}

example