如何在 Three.js 中制作平行曲线用于道路标记?

soi*_*ber 2 javascript bezier curve three.js

I\xc2\xb4m 试图画一些平行线的曲线,一条一条相邻,但如果我通过修改/平移它们在一个轴上的位置来将它们分开,结果不是我想要的。

\n\n

代码很简单,用贝塞尔曲线制作中央路径,并用其他材料克隆侧面。

\n\n
var bezier = new THREE.CubicBezierCurve3(\n                new THREE.Vector3(initx, inity, 0),\n                new THREE.Vector3(cp1x, cp1y, 0),\n                new THREE.Vector3( cp2x, cp2y, 0),\n                new THREE.Vector3(finalx, finaly, 0)\n                );\n\nvar curvePath = new THREE.CurvePath();\ncurvePath.add(bezier);\n\nvar path = curvePath.createPointsGeometry( 5 );\npath.computeLineDistances();\n\nvar lineMat = new THREE.LineDashedMaterial({ color: 0xFFFFFF,\n                                             dashSize: 3,\n                                             gapSize: 2, \n                                             linewidth: 10});\n\nvar curveLine = new THREE.Line(path, lineMat);\n\ncurveLine.rotation.set(-Math.PI/2,0,0);\ncurveLine.position.y = 0.1;\n\nvar leftLine = curveLine.clone();\nleftLine.material = matLine;\n\nvar rightLine = curveLine.clone();\nrightLine.material = matLine;\n\nleftLine.translateX(-3.5);\nrightLine.position.set(3.5,0,0);\n\nscene.add(curveLine);\nscene.add(leftLine);\ncurveLine.add(rightLine);\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是结果:\n在此输入图像描述

\n\n

这是我正在寻找的一些示例:

\n\n

d来源:https://pomax.github.io/bezierjs/来源:https://pomax.github.io/bezierjs/

\n\n

最后两张图片来自Bezier.js库。

\n\n

我认为对曲线应用偏移,使用法线绘制另一条线可能是解决方案,但我在文档中找不到任何有用的内容。\n我认为也可以从切轴的距离画一条线或类似的东西,但这可能是一种更简单的方法,有什么想法吗?

\n\n

我看过这个,但它是直线。

\n

soi*_*ber 5

最后,我自己做了。

我使用 getTangent() 计算主曲线在其点上的切线法线,并将其旋转 90 度以获得法线。我为该法线创建了更多顶点,并将其值乘以标量。然后,我 从世界坐标中的法线中得到了我想要的点,并将它们连接起来,创建了一个 CatmullRomCurve3 几何体:

for(var i = 0.0; i <= 1.0; i += 0.2){

    var point = curvePath.getPointAt(i);

    var tangent = curvePath.getTangent(i);
    var extension1 = new THREE.Vector3(tangent.x*2, tangent.y*2, 0);
    var extension2 = new THREE.Vector3(extension1.x*2, extension1.y*2, 0);

    var tangentGeometry = new THREE.Geometry();
    tangentGeometry.vertices.push(tangent, extension1, extension2);

    var tangentLine = new THREE.Line(tangentGeometry,greenMaterial);
    tangentLine.position.set(point.x, point.y, point.z);

    normal.updateMatrixWorld(); // VERY IMPORTANT

    var normal = tangentLine.clone();
    normal.rotateZ(Math.PI/2);

    var normalLastVertex = normal.geometry.vertices[2].clone();
    normalLastVertex.applyMatrix4(normal.matrixWorld); //convert to world coords.

    pointsArray.push(normalLastVertex); //for using them out of the loop

    curveLine.add(tangentLine);
    curveLine.add(normal);
}
Run Code Online (Sandbox Code Playgroud)

这里我在点数组中有最后一个法线顶点,所以我必须创建将它们连接到循环之外的样条线。

    var splineCurveOffsetLeft = new THREE.CatmullRomCurve3([

       new THREE.Vector3((pointsArray[0].x), pointsArray[0].y, 0),
       new THREE.Vector3((pointsArray[1].x), pointsArray[1].y, 0),
       new THREE.Vector3((pointsArray[2].x), pointsArray[2].y, 0),
       new THREE.Vector3((pointsArray[3].x), pointsArray[3].y, 0),
       new THREE.Vector3((pointsArray[4].x), pointsArray[4].y, 0),
       new THREE.Vector3((pointsArray[5].x), pointsArray[5].y, 0)           
    ]);
splineCurveOffsetLeft.type = 'catmullrom';
splineCurveOffsetLeft.closed = false;

var offsetGeometry = new THREE.Geometry();
offsetGeometry.vertices = splineCurveOffsetLeft.getPoints(6);

var offsetLine = new THREE.Line(offsetGeometry, cyanMaterial);

offsetLine.rotation.set(-Math.PI/2, 0, 0);
offsetLine.position.y=0.1;

scene.add(offsetLine);
Run Code Online (Sandbox Code Playgroud)

我对另一条偏移线做了同样的事情,只是反转它的旋转,这就是结果:

偏移曲线

绿色 = 切线,红色 = 法线,青色 = 平行曲线