|
|
|
@ -3,7 +3,8 @@ import type { ItemTypeDefineOption } from '@/model/itemType/ItemTypeDefine.ts' |
|
|
|
import type { ItemJson } from '@/model/WorldModelType.ts' |
|
|
|
import { getAllItemTypes, getItemTypeByName } from '@/runtime/DefineItemType.ts' |
|
|
|
import type Viewport from '@/designer/Viewport.ts' |
|
|
|
import type Toolbox from '@/model/itemType/Toolbox.ts' |
|
|
|
import { computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh' |
|
|
|
import { Vector2 } from 'three/src/math/Vector2' |
|
|
|
|
|
|
|
export function quickCopyByMouse() { |
|
|
|
// 获取鼠标位置,查看鼠标是否在某个 viewport 的画布上,并取得该 viewport
|
|
|
|
@ -13,13 +14,20 @@ export function quickCopyByMouse() { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 从当前 mouse.x, mouse.z 获取地图坐标
|
|
|
|
const viewport: Viewport = currentMouseInfo.viewport |
|
|
|
const x = currentMouseInfo.x |
|
|
|
const z = currentMouseInfo.z |
|
|
|
const point: THREE.Vector2 = currentMouseInfo.mouse |
|
|
|
|
|
|
|
// 如果当前 x,y 命中在某条线上,以当前鼠标为点,插入一个这个线段的起点的相似点,连接两头的点。
|
|
|
|
const ray = new THREE.Raycaster() |
|
|
|
ray.setFromCamera(point, viewport.camera) |
|
|
|
const intersections = ray.intersectObjects(viewport.dragControl._dragObjects, true) |
|
|
|
|
|
|
|
if (intersections.length === 0) { |
|
|
|
system.msg('没有找到可复制的对象') |
|
|
|
return |
|
|
|
} |
|
|
|
console.log('intersections:', intersections) |
|
|
|
|
|
|
|
/* |
|
|
|
// 如果不在线上,查找0.2米内的有效点 Object3D, 如果有,则以这个点为起点, 延伸同类型的点,并让他们相连
|
|
|
|
findObject3DByCondition(viewport.scene, object => { |
|
|
|
// 判断 object 是否是有效的 Object3D, 并且是当前 viewport 的对象
|
|
|
|
@ -39,6 +47,68 @@ export function quickCopyByMouse() { |
|
|
|
} |
|
|
|
return false |
|
|
|
}) |
|
|
|
*/ |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 查找射线周围指定半径内的对象 |
|
|
|
*/ |
|
|
|
export function findObjectsInRadius(viewport: Viewport, |
|
|
|
point: THREE.Vector2, |
|
|
|
radius: number, |
|
|
|
lines: { object: THREE.Object3D, distance: number }[], |
|
|
|
points: { object: THREE.Object3D, distance: number }[] |
|
|
|
): void { |
|
|
|
const ray = new THREE.Raycaster() |
|
|
|
ray.setFromCamera(point, viewport.camera) |
|
|
|
|
|
|
|
viewport.dragControl._dragObjects.forEach(obj => { |
|
|
|
if (obj instanceof THREE.Points) { |
|
|
|
// 处理点云:遍历每个点
|
|
|
|
const distance = distanceToRay(ray, point) |
|
|
|
if (distance <= radius) { |
|
|
|
points.push({ object: obj, distance }) |
|
|
|
} |
|
|
|
|
|
|
|
} else if (obj instanceof THREE.Line) { |
|
|
|
// 处理线段:计算线段到射线的最近距离
|
|
|
|
const distance = getLineDistanceToRay(ray, obj) |
|
|
|
if (distance <= radius) { |
|
|
|
lines.push({ object: obj, distance }) |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 计算点到射线的最短距离 |
|
|
|
*/ |
|
|
|
function distanceToRay(ray: THREE.Raycaster, point: THREE.Vector2) { |
|
|
|
const closestPoint = new THREE.Vector3() |
|
|
|
ray.closestPointToPoint(point, closestPoint) |
|
|
|
return point.distanceTo(closestPoint) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 计算线段到射线的最短距离 |
|
|
|
*/ |
|
|
|
function getLineDistanceToRay(ray: THREE.Raycaster, line: THREE.Line) { |
|
|
|
const lineStart = new THREE.Vector3() |
|
|
|
const lineEnd = new THREE.Vector3() |
|
|
|
line.geometry.attributes.position.getXYZ(0, lineStart) |
|
|
|
line.geometry.attributes.position.getXYZ(1, lineEnd) |
|
|
|
line.localToWorld(lineStart) |
|
|
|
line.localToWorld(lineEnd) |
|
|
|
|
|
|
|
const lineSegment = new THREE.Line3(lineStart, lineEnd) |
|
|
|
const closestOnRay = new THREE.Vector3() |
|
|
|
const closestOnLine = new THREE.Vector3() |
|
|
|
THREE.Line3.prototype.closestPointsRayLine ??= function(ray, line, closestOnRay, closestOnLine) { |
|
|
|
// 实现射线与线段最近点计算(需自定义或使用数学库)
|
|
|
|
} |
|
|
|
|
|
|
|
lineSegment.closestPointsRayLine(ray, true, closestOnRay, closestOnLine) |
|
|
|
return closestOnRay.distanceTo(closestOnLine) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
|