You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Three.js中高效计算两个向量的交点?

Efficiently Finding Intersections Between Two Vectors/Rays/Segments in Three.js

Great question—let’s break this down clearly, since there’s a common terminology mix-up here first: when you say "vector," you’re probably referring to either a finite line segment or an infinite/half-infinite ray (since pure vectors are just direction/magnitude, not positioned in space). Your initial approach has a small logic gap, but Three.js does have built-in tools to make this way cleaner.

First, Correcting Your Initial Approach

Your idea of converting one "vector" to a ray and checking intersections is on the right track, but the distance check is off. Instead of checking if the intersection is 0 distance from the first vector’s origin, you need to verify the intersection lies within the bounds of your original geometric object:

  • For a ray: the intersection must be along the ray’s direction (i.e., the parameter t in the ray equation is ≥ 0)
  • For a line segment: the intersection must lie between the segment’s two endpoints

Three.js Built-in Tools for Intersection Checks

Three.js has optimized methods to handle these cases without writing raw linear algebra from scratch:

1. Ray vs. Line Segment Intersection

If you’re working with a ray and a finite line segment, use the Ray.intersectSegment() method—it’s built to handle this efficiently, including edge cases like parallel lines or collinear segments.

Example code:

// Define your ray (origin + normalized direction)
const rayOrigin = new THREE.Vector3(0, 0, 0);
const rayDirection = new THREE.Vector3(1, 1, 0).normalize();
const ray = new THREE.Ray(rayOrigin, rayDirection);

// Define your line segment (two endpoints)
const segStart = new THREE.Vector3(2, 0, 0);
const segEnd = new THREE.Vector3(0, 2, 0);

// Calculate intersection
const intersectionPoint = new THREE.Vector3();
const doesIntersect = ray.intersectSegment(segStart, segEnd, intersectionPoint);

if (doesIntersect) {
  console.log("Intersection found at:", intersectionPoint);
} else {
  console.log("No intersection between ray and segment");
}

2. Line Segment vs. Line Segment Intersection

Three.js doesn’t have a direct built-in method for this, but you can combine the Ray.intersectSegment() method with a bounds check to validate the intersection lies on both segments:

function findSegmentIntersection(seg1Start, seg1End, seg2Start, seg2End) {
  // Create a ray along the first segment
  const seg1Direction = seg1End.clone().sub(seg1Start).normalize();
  const ray = new THREE.Ray(seg1Start, seg1Direction);

  const intersection = new THREE.Vector3();
  const intersects = ray.intersectSegment(seg2Start, seg2End, intersection);

  if (!intersects) return null;

  // Check if the intersection is within the bounds of the first segment
  const seg1Length = seg1Start.distanceTo(seg1End);
  const distToSeg1Start = intersection.distanceTo(seg1Start);
  
  // Use a small epsilon to handle floating-point precision errors
  const epsilon = 0.0001;
  if (distToSeg1Start >= -epsilon && distToSeg1Start <= seg1Length + epsilon) {
    return intersection.clone();
  }

  return null;
}

// Usage example
const seg1A = new THREE.Vector3(0, 0, 0);
const seg1B = new THREE.Vector3(2, 2, 0);
const seg2A = new THREE.Vector3(0, 2, 0);
const seg2B = new THREE.Vector3(2, 0, 0);

const intersection = findSegmentIntersection(seg1A, seg1B, seg2A, seg2B);
if (intersection) {
  console.log("Segment intersection at:", intersection); // Should log (1,1,0)
}

3. Ray vs. Ray Intersection

For two infinite rays, you’ll need to solve the linear system manually (Three.js doesn’t have a built-in method for this), but it’s straightforward:

function findRayIntersection(ray1, ray2) {
  const denominator = ray1.direction.clone().cross(ray2.direction).lengthSq();
  
  // If denominator is 0, rays are parallel (no unique intersection)
  if (denominator < 0.0001) return null;

  const t = ray2.origin.clone().sub(ray1.origin).cross(ray2.direction).dot(ray1.direction.clone().cross(ray2.direction)) / denominator;
  const s = ray2.origin.clone().sub(ray1.origin).cross(ray1.direction).dot(ray1.direction.clone().cross(ray2.direction)) / denominator;

  // Check if both parameters are non-negative (since rays only go forward from origin)
  if (t >= -0.0001 && s >= -0.0001) {
    return ray1.at(t, new THREE.Vector3());
  }

  return null;
}

Key Takeaways

  • Always use Three.js’s built-in Ray methods when possible—they handle floating-point edge cases and optimizations you might miss.
  • For segment intersections, don’t forget to validate the intersection lies within both segments’ bounds.
  • Avoid raw distance checks like "distance to origin is 0"—that only checks if the intersection is exactly the ray’s origin, not if it’s along the ray/segment.

内容的提问来源于stack exchange,提问作者zelenooq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:08:12