【纯JavaScript 三维 扇形 圆 标绘 箭头 贝塞尔曲线】

纯JavaScript 三维 扇形 圆 标绘 箭头 贝塞尔曲线

在这里插入图片描述

1.创建扇形、圆

代码如下(示例):


/**
 * 根据起点,终点,创建扇形面
 * @param {*} startPoint 起点坐标
 * @param {*} endPoint 终点坐标
 * @param {*} showAngle 扇形弧度 (0 - 360)
 * @param {*} n 边数复杂度(太大会出现锯齿现场默认半径5倍)
 */
function createSectorPolygonByPoint(startPoint, endPoint, showAngle, n, addR = 0) {
    let r = Math.sqrt(Math.pow(endPoint[0] - startPoint[0], 2) + Math.pow(endPoint[1] - startPoint[1], 2) + Math.pow(endPoint[2] - startPoint[2], 2)) + addR;
    if (!n) {
        n = r * 5;
        n < 20 && (n = 20);
        n > 20 && (n = 100);
    }
    let sAnale = getTheta(startPoint, endPoint, 90);
    let [x, y, z] = startPoint;
    let points = [startPoint];
    let angle = Math.PI + sAnale - Math.PI * showAngle / 360;
    let counterclockwise = false;
    points.push([x + r * Math.sin(angle),       //从第一个顶点开始一条新的子路径
    y - r * Math.cos(angle), z])
    var delta = 2 * Math.PI / n;            //两个顶点之间的夹角
    var maxCount = parseInt(n * showAngle / 360);
    for (var i = 1; i < maxCount; i++) {          //循环剩余的每个顶点
        angle += counterclockwise ? -delta : delta;   //调整角度
        points.push([x + r * Math.sin(angle),   //以下个顶点为端点添加线段
        y - r * Math.cos(angle), z]);
    }
    return points;
}

//计算与X轴夹角 并偏移pn(0-360)(三角)
function getTheta(p1, p2, pn = 0) {
    let angle = Math.atan2((p2[1] - p1[1]), (p2[0] - p1[0]));
    angle -= Math.PI * pn / 180;
    return angle;
}

2.各类箭头标绘

代码如下(示例):


/**
 * 根据两点绘制标准箭头(两点式)
 * @param {*} endPoint 终点
 * @param {*} startPoint  起点
 * @param {*} outAngle 外角度 0 - 180
 * @param {*} inAngle 内角度 0 - 180
 * @param {*} inAngle 内角度 0 - 180
 * @param {*} ratio 箭头长度占比
 * @param {*} concave 缩进比例
 * @returns 
 */
function arrow1(endPoint, startPoint, outAngle = 60, inAngle = 40, Angle = 10, ratio = 0.2, concave = 0.15) {
    let r = Math.sqrt(Math.pow(endPoint[0] - startPoint[0], 2) + Math.pow(endPoint[1] - startPoint[1], 2) + Math.pow(endPoint[2] - startPoint[2], 2));
    let r2 = r * ratio;
    let r3 = r * concave;

    //计算与X轴夹角 并偏移pn(0-360)(三角)
    let pn = 90;//默认0°
    let sAnale = Math.atan2((endPoint[1] - startPoint[1]), (endPoint[0] - startPoint[0]));
    sAnale -= Math.PI * 90 / 180;

    let [x, y, z] = startPoint;
    let points = [startPoint];
    //外1左
    let angle = Math.PI + sAnale - Math.PI * outAngle / 360;
    points.push([x + r2 * Math.sin(angle), y - r2 * Math.cos(angle), z]);

    //外2左
    angle = Math.PI + sAnale - Math.PI * inAngle / 360;
    points.push([x + r3 * Math.sin(angle), y - r3 * Math.cos(angle), z]);

    //外3左
    angle = Math.PI + sAnale - Math.PI * Angle / 360;
    points.push([x + r * Math.sin(angle), y - r * Math.cos(angle), z]);

    //外3右
    angle = Math.PI + sAnale + Math.PI * Angle / 360;
    points.push([x + r * Math.sin(angle), y - r * Math.cos(angle), z]);


    //外2右
    angle = Math.PI + sAnale + Math.PI * inAngle / 360;
    points.push([x + r3 * Math.sin(angle), y - r3 * Math.cos(angle), z]);

    //外1右
    angle = Math.PI + sAnale + Math.PI * outAngle / 360;
    points.push([x + r2 * Math.sin(angle), y - r2 * Math.cos(angle), z]);

    // points.push(startPoint);
    return points;
}

/**
 * 根据两点绘制标准箭头(某段箭头形式)(两点式)
 * @param {*} endPoint 终点
 * @param {*} startPoint  起点
 * @param {*} outAngle 外角度 0 - 180
 * @param {*} inAngle 内角度 0 - 180
 * @param {*} inAngle 内角度 0 - 180
 * @param {*} ratio 箭头长度占比
 * @param {*} concave 缩进比例
 * @param {*} endConcave 末端缩进比例
 * @returns 
 */
function arrow2(endPoint, startPoint, outAngle = 60, inAngle = 40, Angle = 10, ratio = 0.2, concave = 0.15, endConcave = 0.05) {
    let r = Math.sqrt(Math.pow(endPoint[0] - startPoint[0], 2) + Math.pow(endPoint[1] - startPoint[1], 2) + Math.pow(endPoint[2] - startPoint[2], 2));
    let r2 = r * ratio;
    let r3 = r * concave;
    let r4 = r * (1 - endConcave);

    //计算与X轴夹角 并偏移pn(0-360)(三角)
    let pn = 90;//默认0°
    let sAnale = Math.atan2((endPoint[1] - startPoint[1]), (endPoint[0] - startPoint[0]));
    sAnale -= Math.PI * 90 / 180;

    let [x, y, z] = startPoint;
    let points = [startPoint];
    //外1左
    let angle = Math.PI + sAnale - Math.PI * outAngle / 360;
    points.push([x + r2 * Math.sin(angle), y - r2 * Math.cos(angle), z]);

    //外2左
    angle = Math.PI + sAnale - Math.PI * inAngle / 360;
    points.push([x + r3 * Math.sin(angle), y - r3 * Math.cos(angle), z]);

    //外3左
    angle = Math.PI + sAnale - Math.PI * Angle / 360;
    points.push([x + r * Math.sin(angle), y - r * Math.cos(angle), z]);

    //中末端点
    angle = Math.PI + sAnale;
    points.push([x + r4 * Math.sin(angle), y - r4 * Math.cos(angle), z]);

    //外3右
    angle = Math.PI + sAnale + Math.PI * Angle / 360;
    points.push([x + r * Math.sin(angle), y - r * Math.cos(angle), z]);


    //外2右
    angle = Math.PI + sAnale + Math.PI * inAngle / 360;
    points.push([x + r3 * Math.sin(angle), y - r3 * Math.cos(angle), z]);

    //外1右
    angle = Math.PI + sAnale + Math.PI * outAngle / 360;
    points.push([x + r2 * Math.sin(angle), y - r2 * Math.cos(angle), z]);

    return points;
}


/**
 * 根据两点绘制标准箭头(二次贝塞尔曲线)(三点式)
 * @param {*} endPoint 终点
 * @param {*} startPoint  起点
 * @param {*} outAngle 外角度 0 - 180
 * @param {*} inAngle 内角度 0 - 180
 * @param {*} inAngle 内角度 0 - 180
 * @param {*} ratio 箭头长度占比
 * @param {*} concave 缩进比例
 * @param {*} endConcave 末端缩进比例
 * @returns 
 */
function arrow3(endPoint, startPoint, centerPoint, outAngle = 60, inAngle = 40, Angle = 10, ratio = 0.2, concave = 0.15, endConcave = 0.05) {
    let r11 = Math.sqrt(Math.pow(centerPoint[0] - startPoint[0], 2) + Math.pow(centerPoint[1] - startPoint[1], 2) + Math.pow(centerPoint[2] - startPoint[2], 2));
    let r22 = Math.sqrt(Math.pow(endPoint[0] - centerPoint[0], 2) + Math.pow(endPoint[1] - centerPoint[1], 2) + Math.pow(endPoint[2] - centerPoint[2], 2));
    let r2 = r11 * ratio;
    let r3 = r11 * concave;
    let r4 = r22 * (1 - endConcave);

    //计算与X轴夹角 并偏移pn(0-360)(三角)
    let pn = 90;//默认0°
    let sAnale = Math.atan2((endPoint[1] - startPoint[1]), (endPoint[0] - startPoint[0]));
    sAnale -= Math.PI * 90 / 180;

    let sAnale1 = Math.atan2((centerPoint[1] - startPoint[1]), (centerPoint[0] - startPoint[0]));
    sAnale1 -= Math.PI * 90 / 180;

    let sAnale2 = Math.atan2((endPoint[1] - centerPoint[1]), (endPoint[0] - centerPoint[0]));
    sAnale2 -= Math.PI * 90 / 180;

    let [x, y, z] = startPoint;
    let [x2, y2, z2] = centerPoint;
    let points = [startPoint];
    //外1左
    let angle = Math.PI + sAnale1 - Math.PI * outAngle / 360;
    points.push([x + r2 * Math.sin(angle), y - r2 * Math.cos(angle), z]);

    //外2左
    angle = Math.PI + sAnale1 - Math.PI * inAngle / 360;
    let _l2 = [x + r3 * Math.sin(angle), y - r3 * Math.cos(angle), z];

    //外3左
    angle = Math.PI + sAnale2 - Math.PI * Angle / 360;
    let _l3 = [x2 + r22 * Math.sin(angle), y2 - r22 * Math.cos(angle), z2];
    points.push(...getBS2Coors(_l2, centerPoint, _l3));

    //中末端点
    angle = Math.PI + sAnale2;
    points.push([x2 + r4 * Math.sin(angle), y2 - r4 * Math.cos(angle), z2]);

    //外3右
    angle = Math.PI + sAnale2 + Math.PI * Angle / 360;
    let _r3 = [x2 + r22 * Math.sin(angle), y2 - r22 * Math.cos(angle), z2];

    //外2右
    angle = Math.PI + sAnale1 + Math.PI * inAngle / 360;
    let _r2 = [x + r3 * Math.sin(angle), y - r3 * Math.cos(angle), z];
    points.push(...getBS2Coors(_r2, centerPoint, _r3).reverse());

    //外1右
    angle = Math.PI + sAnale1 + Math.PI * outAngle / 360;
    points.push([x + r2 * Math.sin(angle), y - r2 * Math.cos(angle), z]);

    // points.push(startPoint);
    return points;
}

/**
 * 根据两点绘制标准箭头(二次贝塞尔曲线)(四点式)
 * @param {*} endPoint 终点
 * @param {*} startPoint  起点
 * @param {*} outAngle 外角度 0 - 180
 * @param {*} inAngle 内角度 0 - 180
 * @param {*} inAngle 内角度 0 - 180
 * @param {*} ratio 箭头长度占比
 * @param {*} concave 缩进比例
 * @param {*} endConcave 末端缩进比例
 * @returns 
 */
function arrow4(endPoint, startPoint, centerPoint, outAngle = 60, inAngle = 40, Angle = 10, ratio = 0.2, concave = 0.15, endConcave = 0.05) {
    let r11 = Math.sqrt(Math.pow(centerPoint[0] - startPoint[0], 2) + Math.pow(centerPoint[1] - startPoint[1], 2) + Math.pow(centerPoint[2] - startPoint[2], 2));
    let r22 = Math.sqrt(Math.pow(endPoint[0] - centerPoint[0], 2) + Math.pow(endPoint[1] - centerPoint[1], 2) + Math.pow(endPoint[2] - centerPoint[2], 2));
    let r2 = r11 * ratio;
    let r3 = r11 * concave;
    let r4 = r22 * (1 - endConcave);

    //计算与X轴夹角 并偏移pn(0-360)(三角)
    let pn = 90;//默认0°
    let sAnale = Math.atan2((endPoint[1] - startPoint[1]), (endPoint[0] - startPoint[0]));
    sAnale -= Math.PI * 90 / 180;

    let sAnale1 = Math.atan2((centerPoint[1] - startPoint[1]), (centerPoint[0] - startPoint[0]));
    sAnale1 -= Math.PI * 90 / 180;

    let sAnale2 = Math.atan2((endPoint[1] - centerPoint[1]), (endPoint[0] - centerPoint[0]));
    sAnale2 -= Math.PI * 90 / 180;

    let [x, y, z] = startPoint;
    let [x2, y2, z2] = centerPoint;
    let points = [startPoint];
    //外1左
    let angle = Math.PI + sAnale1 - Math.PI * outAngle / 360;
    points.push([x + r2 * Math.sin(angle), y - r2 * Math.cos(angle), z]);

    //外2左
    angle = Math.PI + sAnale1 - Math.PI * inAngle / 360;
    let _l2 = [x + r3 * Math.sin(angle), y - r3 * Math.cos(angle), z];

    //外3左
    angle = Math.PI + sAnale2 - Math.PI * Angle / 360;
    let _l3 = [x2 + r22 * Math.sin(angle), y2 - r22 * Math.cos(angle), z2];
    points.push(...getBS2Coors(_l2, centerPoint, _l3));

    //中末端点
    angle = Math.PI + sAnale2;
    points.push([x2 + r4 * Math.sin(angle), y2 - r4 * Math.cos(angle), z2]);

    //外3右
    angle = Math.PI + sAnale2 + Math.PI * Angle / 360;
    let _r3 = [x2 + r22 * Math.sin(angle), y2 - r22 * Math.cos(angle), z2];

    //外2右
    angle = Math.PI + sAnale1 + Math.PI * inAngle / 360;
    let _r2 = [x + r3 * Math.sin(angle), y - r3 * Math.cos(angle), z];
    points.push(...getBS2Coors(_r2, centerPoint, _r3).reverse());

    //外1右
    angle = Math.PI + sAnale1 + Math.PI * outAngle / 360;
    points.push([x + r2 * Math.sin(angle), y - r2 * Math.cos(angle), z]);

    // points.push(startPoint);
    return points;
}

//B(t) =  (1-t)²P0 +2t(1-t)P1+t²P2  [0<t<1] 一次贝塞尔曲线
function getBS1Coors(p0, p1, p2, count = 100) {
    let coors = [];
    for (let i = 0; i < count; i++) {
        let t = i / count;
        let x = (1 - t) * (1 - t) * p0[0] + 2 * t * (1 - t) * p1[0] + t * t * p2[0];
        let y = (1 - t) * (1 - t) * p0[1] + 2 * t * (1 - t) * p1[1] + t * t * p2[1];
        coors.push([x, y, p1[2]]);
    }
    return coors;
}

总结

共同学习

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值