Hello,
I’m trying to create an angle measurement based on 3 points. Points are meant to be dynamic and editable by user by dragging them on the surface of a mesh. I already have the angle but I have some problems showing the arc of the angle. It looks ok up to the point where the angle is 180°. After that the angle value is not increasing but decreasing and the arc is placed on the wrong side of the angle. It shows proper angle size, but it’s on the wrong side of the angle.
Code that I’m using to handle arc creation is following
const updateArc = useCallback(() => {
if (!arcRef.current) return;
// copy vectors, otherwise next calculations have impact on original values
P1.current.copy(start);
P2.current.copy(vertex);
P3.current.copy(end);
const radius = Math.min(P1.current.distanceTo(P2.current), P3.current.distanceTo(P2.current)) / 2;
const P2P1 = new Vector3().subVectors(P1.current, P2.current).normalize();
const P2P3 = new Vector3().subVectors(P3.current, P2.current).normalize();
/**
* calculate angle based on the dot product
* mathematically dot(P2P1,P2P3) = |P2P3|*|P2P3|*cosϕ
* P2P1 & P2P3 are normalized so |P2P1| = |P2P3| = 1
* dot(P2P1,P2P3) = cosϕ
* ϕ = arccos(dot(P2P1,P2P3))
* */
const angle = Math.acos(P2P1.dot(P2P3));
const tempArcPoints: number[] = [];
const quaternion = new Quaternion();
const axis = vertexNormal ?? new Vector3().crossVectors(P2P1, P2P3).normalize();
for (let i = 0; i <= N; i++) {
const stepAngle = angle * (i / N);
const rotatedVector = P2P1.clone()
.applyQuaternion(quaternion.setFromAxisAngle(axis, stepAngle))
.multiplyScalar(radius);
const point = rotatedVector.add(P2.current);
tempArcPoints.push(point.x, point.y, point.z);
}
const geom = new LineGeometry();
geom.setPositions(tempArcPoints.flat());
arc.geometry = geom;
arc.computeLineDistances();
}, [start, vertex, end, vertexNormal, arc]);
and the usage:
<primitive dispose={undefined} object={arc} ref={arcRef}>
<primitive
dispose={undefined}
object={lineMaterial}
attach="material"
color={isActive ? COLOR_TEAL_700 : COLOR_TEAL_200}
resolution={new Vector2(1024, 1024)}
linewidth={1}
depthTest={false}
/>
</primitive>
Angle for this code looks following
i also tried to introduce reference vector (proposed by gpt) which looks llike this :
const referenceVector = new Vector3(0, 1, 0);
const axis =
referenceVector.dot(new Vector3().crossVectors(P2P1, P2P3).normalize()) > 0
? vertexNormal
: vertexNormal?.negate();
and it sometimes works but sometimes not…
Does someone have any idea what would help to track proper arc side/vallue here?