Update Object positioning

I’m creating a network diagram. I have a line that connects two objects and I’m also aligning objects (network interface labels) on that line.

In the scene I’m using drag controls for my object (network routers) and no other controls are configured for the scene.

When dragging the routers I have the points in the line updating and while updating the network interface label positions manually. The issue is the labels positions flip depending on where a node is dragged as seen in the video. Here is the code to update label postions.

const dir = line.geometry.boundingBox.max.clone().sub(center).normalize().multiplyScalar(.85)
    const dirTwo = line.geometry.boundingBox.min.clone().sub(center).normalize().multiplyScalar(.85)

    linkLabelOne.position.set(center.clone().add(dirTwo).x, center.clone().add(dirTwo).y, 0)
    linkLabelTwo.position.set(center.clone().add(dir).x, center.clone().add(dir).y, 0)

Here is the code to update the point postions:

if (groupUuid[group].uuid === lineUuid[i].links.to) {

  const positionsTo = lineUuid[i].geometry.attributes.position.array

  positionsTo[3] = event.object.position.x
  positionsTo[4] = event.object.position.y
  positionsTo[5] = 0

  lineUuid[i].geometry.attributes.position.needsUpdate = true;
  lineUuid[i].geometry.computeBoundingBox();
  lineUuid[i].geometry.computeBoundingSphere();

  setLinkLabels(lineUuid[i].children[0], lineUuid[i].children[1], undefined, lineUuid[i])

} else if (groupUuid[group].uuid === lineUuid[i].links.from) {

  const positionsFrom = lineUuid[i].geometry.attributes.position.array

  positionsFrom[0] = event.object.position.x
  positionsFrom[1] = event.object.position.y
  positionsFrom[2] = 0

  lineUuid[i].geometry.attributes.position.needsUpdate = true;
  lineUuid[i].geometry.computeBoundingBox();
  lineUuid[i].geometry.computeBoundingSphere();

  setLinkLabels(lineUuid[i].children[0], lineUuid[i].children[1], undefined, lineUuid[i])
}
}

I’ve tried to group the line and the labels but i think since I’m only updating the line points and not positions, the label wont move as a group with the line.

As a test I assign drag controls to the line and labels as group and they move as one. Per my design I only want the routers being dragged.

Countless hours and I’m running out of ideas. I think the solution maybe something i don’t understand about three.js yet.

So you have a line in 3D space and you want to position another 3D object (label) above the line at a certain point, counting from one end of the line towards the other as, say, a percentage of the line’s length?

I have the labels positioned as i want , its just when i drag the object in a certain direction you can see the labels flip/rotate depending on the direction. This would make my scene or network topology inaccurate .

It’ll be easier to help you if you posted a minimal working example on codepen or jsfiddle, otherwise it’s hard to tell.

That being said, calculating position on a line and moving an object there takes two lines of code, so yours seems to be way too complex for the task.

As far as complexity, I would love any advice on placing the labels on the lines with less code. They aren’t exactly where I want them as I would like them center on the line. -----[–g0/1–]----. I’ve have a a lot of code for this project but this seems to be my roadblock.

I don’t know how you make labels (I would write text on 2D canvas and then used it as a texture for Point geometry, so your labels always face the camera).

Apart from that here is a simple example of objects tracing start, end and middle points of a line:

Here is how the line and labels is created. This code is executed in two possible ways. With imported data from the backend it creates the scene dynamically, or when someone is creating a diagram using eventListeners for ctrl + leftClick. If 2 devices are selected it creates the line between the two objects.

The labels are always front facing, and for the scene i don’t have any controls configured other than dragControls. This is by design


export const setLinkLabels = (linkLabelOne, linkLabelTwo, line) => {

    const center = line.geometry.boundingBox.getCenter(line.geometry.boundingSphere.center)

    line.geometry.boundingBox.copy(line.geometry.boundingBox).applyMatrix4(line.matrixWorld)

	const dir = line.geometry.boundingBox.max.clone().sub(center).normalize().multiplyScalar(.85)
	const dirTwo = line.geometry.boundingBox.min.clone().sub(center).normalize().multiplyScalar(.85)
	
	linkLabelOne.position.set(center.clone().add(dirTwo).x, center.clone().add(dirTwo).y, 0)
	linkLabelTwo.position.set(center.clone().add(dir).x, center.clone().add(dir).y, 0)

}

export const canvas = (labelText) => {

    const canvas = document.createElement('canvas');
    canvas.width = 256;
    canvas.height = 256;
    const ctx = canvas.getContext("2d");

    ctx.fillStyle = "white";
    ctx.textAlign = "center";
    ctx.strokeStyle = "black";
    ctx.lineWidth = 8;

	ctx.strokeText(labelText, 128, 46);
	ctx.fillText(labelText, 128, 46);


    return canvas

}

 
 const createLabel = (labelText) => {

	const createCanvas = canvas(labelText)
	const texture = new THREE.Texture(createCanvas);
	texture.needsUpdate = true;

	const spriteMat = new THREE.SpriteMaterial({map: texture});

	return new THREE.Sprite(spriteMat)
        

    }
	
 const addLink = (operation) => {
 
	//multiselect.current is the to objects that the line connects. It also has the label text which is applied to canvas
	
	const linkLabelOne = createLabel(multiSelect.current[0].interface)
	const linkLabelTwo = createLabel(multiSelect.current[1].interface)

	const points = [];

	points.push(multiSelect.current[0].position);
	points.push(multiSelect.current[1].position);

	const geometry = new THREE.BufferGeometry().setFromPoints(points);
	const material = new THREE.LineBasicMaterial({color: 0xffffff, depthTest: false});
	const line = new THREE.Line(geometry, material);

	line.links = {from: multiSelect.current[0].uuid, to: multiSelect.current[1].uuid}
	line.renderOrder = 0

	line.geometry.attributes.position.needsUpdate = true;
	line.geometry.computeBoundingBox();
	line.geometry.computeBoundingSphere();

	line.add(linkLabelOne)
	line.add(linkLabelTwo)

	setLinkLabels(linkLabelOne, linkLabelTwo, line)

	scene.current.add(line);
			
}

That also works:

I have two labels as seen in my video. So you would have boom0 —boom1—boom2–boom3. And when rotating it should reposition to

boom3–boom2–boom1–boom0

Im not worried about the z axis either, just x, y as im not adding controls other than dragControls

Like this, three.js examples

In the last fiddle labels go boom0 - boom1 - boom2, when the line flips horizontally, they go boom2 - boom1 - boom0, so labels follow the line ends, as they should, do they not?

I added back the cubes that mark different ends of the line and the middle:

If you want labels to be on the line, that’s how you could it, if you want them to reposition somehow on top of that, then they are not on the line, that’s a different task.

I created a fiddle to simulate the action. Unfortunately I could not get dragControls imported. I was still able to simulate the action shown in my video and it looks like it works properly. Let me review my code to see if i can get it to work,

Cool, I don’t have any custom code for drag controls but if it works w/o them then probably those controls are the issue.