英文:
How to move the Point according the line orientation
问题
我正在使用React THREEJS和一些其他库(DREI,Meshline等)来绘制线条和文本等。现在我正在绘制一条线,我必须同时显示长度标签。应该是这样的。
现在我必须添加一个选项来根据线的方向移动标签位置。例如:
- 垂直线应该在X轴上有(左/右)移动
- 水平线应该在Y轴上有(上/下)移动
我已经计算了向量点(P1/P2)的中间位置。
const P1 = new THREE.Vector3(-300.79, -296.96, 0);
const P2 = new THREE.Vector3(101.49, -8.43, 0);
const disX = (P2.x + P1.x) / 2;
const disY = (P2.y + P1.y) / 2;
const P3 = new THREE.Vector3(disX, disY, 0);
你能给我提供一些建议吗?
英文:
I am using React THREEJS and some other libraries (DREI, Meshline, etc) to draw the Lines and Text, etc. Right Now I am drawing a line and I have to show the length label along with the line. It will be something like this.
Now I have to add an option to move the label position according to line orientation. For example
- Vertical Line should have movement (Left/Right) X-AXIS
- Horizontal Line should have (Top/Bottom) Y-AXIS
I have already calculated the middle position of the Vector Points (P1/P2).
const P1 = new THREE.Vector3(-300.79, -296.96, 0);
const P2 = new THREE.Vector3(101.49, -8.43, 0);
const disX = (P2.x + P1.x) / 2;
const disY = (P2.y + P1.Y) / 2;
const P3 = new THREE.Vector3(disX, disY, 0);
Can you please suggest to me any solution?
答案1
得分: 1
当您知道两点的坐标时,其方向向量 (dir
) 的法线 (norm
) 是 norm(-dir.y, dir.x);
。
英文:
When you know coordinates of two points, the normal (norm
) to the vector of their direction (dir
) is norm(-dir.y, dir.x);
Here is an example (not the ultimate solution):
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
body{
overflow: hidden;
margin: 0;
}
<!-- language: lang-html -->
<script async src="https://ga.jspm.io/npm:es-module-shims@1.6.3/dist/es-module-shims.js" crossorigin="anonymous"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.153.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.153.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from "three";
console.clear();
let scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
let frustumSize = 10;
let aspect = innerWidth / innerHeight;
let camera = new THREE.OrthographicCamera(frustumSize * aspect / - 2, frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 1, 100);
camera.position.set(0, 0, 10);
camera.lookAt(scene.position);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", (event) => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
let pts = [
new THREE.Vector2(-3, 3),
new THREE.Vector2(-3, -2),
new THREE.Vector2(2, -3),
new THREE.Vector2(3, 3.5)
];
for(let i = 0; i < pts.length; i++){
let p1 = pts[i];
setPoint(p1);
if (i == pts.length - 1) continue;
let p2 = pts[i+1];
setLine(p1, p2);
let midP = new THREE.Vector3().lerpVectors(p1, p2, 0.5);
let shift = new THREE.Vector2().subVectors(p2, p1).normalize();
let angle = shift.angle();
let swapX = shift.x;
let swapY = shift.y;
shift.set(-swapY, swapX).negate().setLength(0.5);
let distance = p1.distanceTo(p2);
setMarker(midP, shift, angle, distance);
}
function setPoint(pos){
let g = new THREE.RingGeometry(0.5, 1, 32);
let m = new THREE.MeshBasicMaterial({color: "teal"});
let o = new THREE.Mesh(g, m);
o.scale.setScalar(0.1);
o.position.set(pos.x, pos.y, 0.01);
scene.add(o);
}
function setLine(pos1, pos2){
let g = new THREE.BufferGeometry().setFromPoints([pos1, pos2]);
let m = new THREE.LineBasicMaterial({color: "maroon"});
let l = new THREE.Line(g, m);
scene.add(l);
}
function setMarker(pos, shift, angle, distance){
let g = new THREE.PlaneGeometry(4, 1);
let m = new THREE.MeshBasicMaterial({
color: "black",
transparent: true,
map: getDistanceTexture(distance)
});
let o = new THREE.Mesh(g, m);
o.position.set(pos.x + shift.x, pos.y + shift.y, 0);
o.rotation.z = angle;
o.scale.setScalar(1);
scene.add(o);
}
function getDistanceTexture(value){
let text = value.toFixed(1) + "m";
let c = document.createElement("canvas");
c.width = 64 * 4;
c.height = 64;
let ctx = c.getContext("2d");
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "60px Arial";
ctx.fillStyle = "white";
ctx.fillText(text, 64 * 2, 64 / 2);
let ct = new THREE.CanvasTexture(c);
return ct;
}
renderer.setAnimationLoop((_) => {
renderer.render(scene, camera);
});
</script>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论