I have two lines that will be created by the user at runtime, so the positions of these two lines are dynamic. I want one line to coincide with another line as shown in the below image.
How should I proceed
Here is my code
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 15;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById("app").appendChild(renderer.domElement);
let point1 = new THREE.Vector3(14, 25, -159);
let point2 = new THREE.Vector3(-5, 2, 65);
let rightLine = createLine(point1, point2);
let point1LineTwo = new THREE.Vector3(-45, 11, -4);
let point2LineTwo = new THREE.Vector3(-26, -8, -30);
let leftLine = createLine(point1LineTwo, point2LineTwo);
function createLine(point1, point2) {
const linePoints = [];
linePoints.push(new THREE.Vector3(point1.x, point1.y, point1.z));
linePoints.push(new THREE.Vector3(point2.x, point2.y, point2.z));
let lineGeometry = new THREE.BufferGeometry().setFromPoints(linePoints);
var lineMaterial = new THREE.LineBasicMaterial({
color: 0xff5555,
linewidth: 2,
});
let line = new THREE.Line(lineGeometry, lineMaterial);
scene.add(line);
return line;
}
function makeCoincident() {
let rightLineVector = new THREE.Vector3();
const positions = rightLine.geometry.attributes.position.array;
rightLineVector.x = positions[3] - positions[0];
rightLineVector.y = positions[4] - positions[1];
rightLineVector.z = positions[5] - positions[2];
let leftLineVector = new THREE.Vector3();
const lineLeftPosition = leftLine.geometry.attributes.position.array;
leftLineVector.x = lineLeftPosition[3] - lineLeftPosition[0];
leftLineVector.y = lineLeftPosition[4] - lineLeftPosition[1];
leftLineVector.z = lineLeftPosition[5] - lineLeftPosition[2];
//Calulate angle Between leftLineVector and rightLineVector
let angle = leftLineVector.clone().angleTo(rightLineVector);
//calculate cross prduct of lineOneVector and lineTwoVector
let crossPoductVector = new THREE.Vector3();
crossPoductVector.crossVectors(leftLineVector, rightLineVector);
crossPoductVector.normalize();
rightLineVector.applyAxisAngle(crossPoductVector.clone(), angle);
//align right line on left line
var axis = new THREE.Vector3(0, 1, 0);
rightLine.quaternion.setFromUnitVectors(
axis,
rightLineVector.clone().normalize()
);
}
window.addEventListener("keydown", function (event) {
switch (event.keyCode) {
case 81: // Q
makeCoincident();
break;
default:
}
});
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
I created a sandbox [ Link to code sandbox where I created the same problem without dynamic line creation.
I have two lines with random position. one function named makeCoincident()
which makes them coincident which gets called when you press Q key. I tried to solve it but it is not working if you can look into sandbox and tell me where I am going wrong and what is the solution It will be big help thanks
The code you gave is confusing because of the right and left naming. I rewrote the makeCoincident
function
https://codepen.io/cdeep/pen/dydQKoV
To summarize briefly, I first move the vertices of the green line to make the center of the green line intersect with the center of the red. And then, set the vertices of green to a point on the extension of red corresponding to the length of green line.
There is infact, no need to move the green line to make intersecting centres. It's just for clarity incase there's a requirement to make them intersecting without the need for coinciding. Can be omitted for the current question.
function makeCoincident() {
const greenLinePositions = rightLine.geometry.attributes.position.array;
const redLinePositions = leftLine.geometry.attributes.position.array;
const greenLineCenter = new THREE.Vector3(
(greenLinePositions[3] + greenLinePositions[0]) * 0.5,
(greenLinePositions[4] + greenLinePositions[1]) * 0.5,
(greenLinePositions[5] + greenLinePositions[2]) * 0.5,
);
const redLineCenter = new THREE.Vector3(
(redLinePositions[3] + redLinePositions[0]) * 0.5,
(redLinePositions[4] + redLinePositions[1]) * 0.5,
(redLinePositions[5] + redLinePositions[2]) * 0.5,
);
const translationVector = redLineCenter.clone().sub(greenLineCenter);
// Vector pointing from center of green to center of red
const translationArray = translationVector.toArray();
for(let i = 0; i < 6; i++) {
greenLinePositions[i] = greenLinePositions[i] + translationArray[i % 3];
// Move vertices of green line towards red
}
rightLine.geometry.attributes.position.needsUpdate = true;
// Centres of red and green now intersect
const greenLineLength = new THREE.Vector3(
greenLinePositions[0] - greenLinePositions[3],
greenLinePositions[1] - greenLinePositions[4],
greenLinePositions[2] - greenLinePositions[5],
).length();
const redLineDirection = new THREE.Vector3(
redLinePositions[0] - redLinePositions[3],
redLinePositions[1] - redLinePositions[4],
redLinePositions[2] - redLinePositions[5],
).normalize();
// Get new positions of green on the extension of red
const greenPoint1 = redLineCenter.clone().add(redLineDirection.clone().multiplyScalar(greenLineLength * 0.5));
const greenPoint2 = redLineCenter.clone().add(redLineDirection.clone().multiplyScalar(greenLineLength * -0.5));
// Set the attribute values from the new position vectors
greenLinePositions[0] = greenPoint1.x;
greenLinePositions[1] = greenPoint1.y;
greenLinePositions[2] = greenPoint1.z;
greenLinePositions[3] = greenPoint2.x;
greenLinePositions[4] = greenPoint2.y;
greenLinePositions[5] = greenPoint2.z;
rightLine.geometry.attributes.position.needsUpdate = true;
}