2021-04-07 03:46:16 +08:00
|
|
|
import * as THREE from '../node_modules/three/src/Three';
|
|
|
|
import { color } from './shared'
|
2021-04-03 12:05:28 +08:00
|
|
|
|
|
|
|
const lineMaterial = new THREE.LineBasicMaterial({
|
|
|
|
linewidth: 2,
|
2021-04-05 11:52:17 +08:00
|
|
|
color: color.dimension,
|
2021-04-09 07:05:52 +08:00
|
|
|
opacity: 0.2,
|
|
|
|
transparent: true,
|
2021-04-03 12:05:28 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const pointMaterial = new THREE.PointsMaterial({
|
2021-04-05 11:52:17 +08:00
|
|
|
color: color.dimension,
|
2021-04-03 12:05:28 +08:00
|
|
|
size: 4,
|
|
|
|
})
|
|
|
|
|
|
|
|
|
2021-04-04 08:59:14 +08:00
|
|
|
export async function drawDimension() {
|
2021-04-09 07:05:52 +08:00
|
|
|
let selection = await this.awaitSelection({ point: 2 }, { point: 1, line: 1 })
|
|
|
|
|
|
|
|
if (selection == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-03 03:33:09 +08:00
|
|
|
|
|
|
|
|
2021-04-04 08:59:14 +08:00
|
|
|
const line = new THREE.LineSegments(
|
|
|
|
new THREE.BufferGeometry().setAttribute('position',
|
2021-04-04 10:08:19 +08:00
|
|
|
new THREE.Float32BufferAttribute(3 * 8, 3)
|
2021-04-04 08:59:14 +08:00
|
|
|
),
|
|
|
|
lineMaterial.clone()
|
|
|
|
);
|
|
|
|
|
|
|
|
const point = new THREE.Points(
|
|
|
|
new THREE.BufferGeometry().setAttribute('position',
|
2021-04-04 10:08:19 +08:00
|
|
|
new THREE.Float32BufferAttribute(3, 3)
|
2021-04-04 08:59:14 +08:00
|
|
|
),
|
|
|
|
pointMaterial.clone()
|
2021-04-03 03:33:09 +08:00
|
|
|
)
|
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
line.userData.ids = selection.map(e => e.name)
|
|
|
|
|
|
|
|
|
2021-04-04 10:08:19 +08:00
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
|
2021-04-05 16:05:53 +08:00
|
|
|
|
|
|
|
let dist = 0
|
2021-04-09 07:05:52 +08:00
|
|
|
let ptLineOrder;
|
|
|
|
|
|
|
|
if (selection.every(e => e.userData.type == 'point')) {
|
|
|
|
for (let i = 0; i < 3; i++) {
|
|
|
|
dist += (selection[0].geometry.attributes.position.array[i] - selection[1].geometry.attributes.position.array[i]) ** 2
|
|
|
|
}
|
|
|
|
dist = Math.sqrt(dist)
|
|
|
|
} else {
|
|
|
|
ptLineOrder = selection[0].userData.type == 'point' ? [0, 1] : [1, 0]
|
|
|
|
|
|
|
|
const lineArr = selection[ptLineOrder[1]].geometry.attributes.position.array
|
|
|
|
const ptArr = selection[ptLineOrder[0]].geometry.attributes.position.array
|
|
|
|
|
|
|
|
p1.set(lineArr[0], lineArr[1])
|
|
|
|
p2.set(lineArr[3], lineArr[4])
|
|
|
|
p3.set(ptArr[0], ptArr[1])
|
|
|
|
dir = p2.clone().sub(p1).normalize()
|
|
|
|
hyp = p3.clone().sub(p1)
|
|
|
|
proj = dir.multiplyScalar(hyp.dot(dir))
|
|
|
|
perp = hyp.clone().sub(proj)
|
|
|
|
|
|
|
|
dist = Math.sqrt(perp.x ** 2 + perp.y ** 2)
|
|
|
|
|
2021-04-05 16:05:53 +08:00
|
|
|
}
|
2021-04-09 07:05:52 +08:00
|
|
|
|
2021-04-05 16:05:53 +08:00
|
|
|
|
|
|
|
this.obj3d.children[1].add(line).add(point)
|
2021-04-04 10:08:19 +08:00
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
const onMove = this._onMoveDimension(point, line)
|
|
|
|
|
|
|
|
|
|
|
|
point.label = document.createElement('div');
|
2021-04-05 16:05:53 +08:00
|
|
|
point.label.textContent = dist.toFixed(3);
|
|
|
|
point.label.contentEditable = true;
|
2021-04-05 11:52:17 +08:00
|
|
|
this.labelContainer.append(point.label)
|
2021-04-03 03:33:09 +08:00
|
|
|
|
2021-04-03 12:05:28 +08:00
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
|
|
|
|
let onEnd, onKey;
|
2021-04-04 10:08:19 +08:00
|
|
|
let add = await new Promise((res) => {
|
2021-04-04 12:54:27 +08:00
|
|
|
onEnd = (e) => res(true)
|
|
|
|
onKey = (e) => e.key == 'Escape' && res(false)
|
|
|
|
|
2021-04-04 08:59:14 +08:00
|
|
|
this.canvas.addEventListener('pointermove', onMove)
|
|
|
|
this.canvas.addEventListener('pointerdown', onEnd)
|
|
|
|
window.addEventListener('keydown', onKey)
|
|
|
|
})
|
2021-04-03 03:33:09 +08:00
|
|
|
|
2021-04-04 08:59:14 +08:00
|
|
|
this.canvas.removeEventListener('pointermove', onMove)
|
|
|
|
this.canvas.removeEventListener('pointerdown', onEnd)
|
2021-04-04 12:54:27 +08:00
|
|
|
window.removeEventListener('keydown', onKey)
|
2021-04-05 11:52:17 +08:00
|
|
|
point.geometry.computeBoundingSphere()
|
|
|
|
line.geometry.computeBoundingSphere()
|
2021-04-09 07:05:52 +08:00
|
|
|
|
2021-04-04 10:08:19 +08:00
|
|
|
if (add) {
|
2021-04-09 07:05:52 +08:00
|
|
|
if (ptLineOrder) {
|
|
|
|
this.constraints.set(++this.c_id, //???
|
|
|
|
[
|
|
|
|
'pt_line_distance', dist,
|
|
|
|
[selection[ptLineOrder[0]].name, -1, selection[ptLineOrder[1]].name, -1]
|
|
|
|
]
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
this.constraints.set(++this.c_id, //???
|
|
|
|
[
|
|
|
|
'pt_pt_distance', dist,
|
|
|
|
[selection[0].name, selection[1].name, -1, -1]
|
|
|
|
]
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
selection[0].userData.constraints.push(this.c_id)
|
|
|
|
selection[1].userData.constraints.push(this.c_id)
|
2021-04-04 12:54:27 +08:00
|
|
|
|
2021-04-04 10:08:19 +08:00
|
|
|
this.updateOtherBuffers()
|
|
|
|
|
|
|
|
line.name = this.c_id
|
2021-04-05 11:52:17 +08:00
|
|
|
line.userData.type = 'dimension'
|
2021-04-04 10:08:19 +08:00
|
|
|
point.name = this.c_id
|
2021-04-05 11:52:17 +08:00
|
|
|
point.userData.type = 'dimension'
|
|
|
|
|
2021-04-05 16:05:53 +08:00
|
|
|
|
2021-04-06 12:52:19 +08:00
|
|
|
|
|
|
|
point.label.addEventListener('focus', this.updateDim(this.c_id))
|
2021-04-05 16:05:53 +08:00
|
|
|
|
|
|
|
|
2021-04-04 10:08:19 +08:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2021-04-05 16:05:53 +08:00
|
|
|
this.obj3d.children[1].children.splice(this.obj3d.children[1].length - 2, 2).forEach(
|
2021-04-04 10:08:19 +08:00
|
|
|
e => {
|
|
|
|
e.geometry.dispose()
|
|
|
|
e.material.dispose()
|
|
|
|
}
|
|
|
|
)
|
2021-04-05 16:05:53 +08:00
|
|
|
this.labelContainer.removeChild(this.labelContainer.lastChild);
|
2021-04-04 10:08:19 +08:00
|
|
|
sc.render()
|
|
|
|
}
|
2021-04-03 03:33:09 +08:00
|
|
|
|
2021-04-03 12:05:28 +08:00
|
|
|
return
|
2021-04-03 03:33:09 +08:00
|
|
|
}
|
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
const p1 = new THREE.Vector2()
|
2021-04-09 07:05:52 +08:00
|
|
|
const p1x = new THREE.Vector2()
|
2021-04-05 11:52:17 +08:00
|
|
|
const p2 = new THREE.Vector2()
|
|
|
|
const p3 = new THREE.Vector2()
|
2021-04-09 07:05:52 +08:00
|
|
|
let dir, hyp, proj, perp, p1e, p1eArr, p2e, p2eArr, ids, _p1, _p2, p3Arr
|
|
|
|
let mdpt, proj1, proj2, hyp1, hyp2
|
|
|
|
let dp1e, dp2e, dp12
|
2021-04-06 12:52:19 +08:00
|
|
|
|
|
|
|
export function updateDim(c_id) {
|
|
|
|
return (ev_focus) => {
|
|
|
|
const value = ev_focus.target.textContent
|
|
|
|
document.addEventListener('keydown', (e) => {
|
|
|
|
if (e.key == 'Enter') {
|
|
|
|
e.preventDefault()
|
|
|
|
const ent = this.constraints.get(c_id)
|
|
|
|
ent[1] = parseFloat(ev_focus.target.textContent)
|
|
|
|
this.constraints.set(c_id, ent)
|
|
|
|
this.updateOtherBuffers()
|
|
|
|
this.solve()
|
|
|
|
sc.render()
|
|
|
|
ev_focus.target.blur()
|
|
|
|
this.updateBoundingSpheres()
|
|
|
|
} else if (e.key == 'Escape') {
|
|
|
|
ev_focus.target.textContent = value
|
|
|
|
getSelection().empty()
|
|
|
|
ev_focus.target.blur()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2021-04-09 07:05:52 +08:00
|
|
|
}
|
2021-04-06 12:52:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
export function _onMoveDimension(point, line) {
|
2021-04-04 12:54:27 +08:00
|
|
|
|
2021-04-07 05:10:07 +08:00
|
|
|
ids = line.userData.ids
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-07 05:10:07 +08:00
|
|
|
_p1 = this.obj3d.children[this.objIdx.get(ids[0])].geometry.attributes.position.array
|
|
|
|
_p2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array
|
2021-04-05 11:52:17 +08:00
|
|
|
|
|
|
|
let loc;
|
2021-04-04 12:54:27 +08:00
|
|
|
|
|
|
|
return (e) => {
|
|
|
|
loc = this.getLocation(e)
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-04 12:54:27 +08:00
|
|
|
p3.set(loc.x, loc.y)
|
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
update(
|
|
|
|
line.geometry.attributes.position,
|
2021-04-09 07:05:52 +08:00
|
|
|
point.geometry.attributes.position,
|
|
|
|
_p1, _p2
|
2021-04-05 11:52:17 +08:00
|
|
|
)
|
2021-04-04 17:36:41 +08:00
|
|
|
|
|
|
|
point.userData.offset = hyp.toArray()
|
2021-04-04 12:54:27 +08:00
|
|
|
|
|
|
|
sc.render()
|
|
|
|
}
|
2021-04-04 17:36:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-05 16:05:53 +08:00
|
|
|
export function setDimLines() {
|
|
|
|
|
|
|
|
const restoreLabels = this.labelContainer.childElementCount == 0;
|
|
|
|
|
|
|
|
const dims = this.obj3d.children[1].children
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-05 16:05:53 +08:00
|
|
|
let point, dist;
|
|
|
|
for (let i = 0; i < dims.length; i += 2) {
|
|
|
|
if (restoreLabels) {
|
|
|
|
point = dims[i + 1] // point node is at i+1
|
|
|
|
dist = this.constraints.get(point.name)[1]
|
|
|
|
point.label = document.createElement('div');
|
|
|
|
point.label.textContent = dist.toFixed(3);
|
|
|
|
point.label.contentEditable = true;
|
|
|
|
this.labelContainer.append(point.label)
|
2021-04-09 07:05:52 +08:00
|
|
|
|
2021-04-06 12:52:19 +08:00
|
|
|
point.label.addEventListener('focus', this.updateDim(this.c_id))
|
2021-04-05 16:05:53 +08:00
|
|
|
}
|
|
|
|
|
2021-04-07 05:10:07 +08:00
|
|
|
ids = dims[i].userData.ids
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-07 05:10:07 +08:00
|
|
|
_p1 = this.obj3d.children[this.objIdx.get(ids[0])].geometry.attributes.position.array
|
|
|
|
_p2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array
|
2021-04-05 16:05:53 +08:00
|
|
|
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
const offset = dims[i + 1].userData.offset
|
2021-04-04 17:36:41 +08:00
|
|
|
p3.set(_p1[0] + offset[0], _p1[1] + offset[1])
|
|
|
|
|
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
update(
|
2021-04-05 16:05:53 +08:00
|
|
|
dims[i].geometry.attributes.position,
|
2021-04-09 07:05:52 +08:00
|
|
|
dims[i + 1].geometry.attributes.position,
|
|
|
|
_p1,
|
|
|
|
_p2
|
2021-04-05 11:52:17 +08:00
|
|
|
)
|
|
|
|
}
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
}
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
function update(linegeom, pointgeom, _p1, _p2) {
|
|
|
|
|
|
|
|
if (_p1.length == _p2.length) {
|
|
|
|
p1.set(_p1[0], _p1[1])
|
|
|
|
p2.set(_p2[0], _p2[1])
|
|
|
|
|
|
|
|
dir = p2.clone().sub(p1).normalize()
|
|
|
|
hyp = p3.clone().sub(p1)
|
|
|
|
proj = dir.multiplyScalar(hyp.dot(dir))
|
|
|
|
perp = hyp.clone().sub(proj)
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
p1e = p1.clone().add(perp)
|
|
|
|
p1eArr = p1e.toArray()
|
|
|
|
p2e = p2.clone().add(perp)
|
|
|
|
p2eArr = p2e.toArray()
|
|
|
|
p3Arr = p3.toArray()
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
dp1e = p1e.distanceToSquared(p3)
|
|
|
|
dp2e = p2e.distanceToSquared(p3)
|
|
|
|
dp12 = p1e.distanceToSquared(p2e)
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
linegeom.array.set(p1.toArray(), 0)
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (_p1.length < _p2.length) {
|
|
|
|
p1.set(_p2[0], _p2[1])
|
|
|
|
p1x.set(_p2[3], _p2[4])
|
|
|
|
p2.set(_p1[0], _p1[1])
|
|
|
|
} else {
|
|
|
|
p1.set(_p1[0], _p1[1])
|
|
|
|
p1x.set(_p1[3], _p1[4])
|
|
|
|
p2.set(_p2[0], _p2[1])
|
|
|
|
}
|
|
|
|
|
|
|
|
dir = p1x.clone().sub(p1)
|
|
|
|
mdpt = p1.clone().addScaledVector(dir, 0.5)
|
|
|
|
dir.normalize()
|
|
|
|
|
|
|
|
hyp = p2.clone().sub(mdpt)
|
|
|
|
proj = dir.multiplyScalar(hyp.dot(dir))
|
|
|
|
|
|
|
|
perp = hyp.clone().sub(proj)
|
|
|
|
dp12 = perp.lengthSq()
|
|
|
|
|
|
|
|
perp.normalize()
|
2021-04-04 17:36:41 +08:00
|
|
|
|
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
hyp1 = p3.clone().sub(mdpt)
|
|
|
|
proj1 = perp.clone().multiplyScalar(hyp1.dot(perp))
|
|
|
|
|
|
|
|
hyp2 = p3.clone().sub(p2)
|
|
|
|
proj2 = perp.clone().multiplyScalar(hyp2.dot(perp))
|
|
|
|
|
|
|
|
|
|
|
|
p1eArr = p3.clone().sub(proj1).toArray()
|
|
|
|
p2eArr = p3.clone().sub(proj2).toArray()
|
|
|
|
p3Arr = p3.toArray()
|
|
|
|
|
|
|
|
dp1e = proj1.lengthSq()
|
|
|
|
dp2e = proj2.lengthSq()
|
|
|
|
|
|
|
|
linegeom.array.set(mdpt.toArray(), 0)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
linegeom.array.set(p1eArr, 3)
|
|
|
|
linegeom.array.set(p1eArr, 6)
|
|
|
|
linegeom.array.set(p2eArr, 9)
|
|
|
|
linegeom.array.set(p2eArr, 12)
|
|
|
|
linegeom.array.set(p2.toArray(), 15)
|
|
|
|
if (dp12 >= dp1e && dp12 >= dp2e) {
|
|
|
|
linegeom.array.set(p3Arr, 18)
|
|
|
|
} else {
|
|
|
|
if (dp1e > dp2e) {
|
|
|
|
linegeom.array.set(p2eArr, 18)
|
|
|
|
} else {
|
|
|
|
linegeom.array.set(p1eArr, 18)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
linegeom.array.set(p3Arr, 21)
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-05 11:52:17 +08:00
|
|
|
linegeom.needsUpdate = true;
|
2021-04-04 17:36:41 +08:00
|
|
|
|
2021-04-09 07:05:52 +08:00
|
|
|
pointgeom.array.set(p3Arr)
|
2021-04-05 11:52:17 +08:00
|
|
|
pointgeom.needsUpdate = true;
|
2021-04-09 07:05:52 +08:00
|
|
|
|
|
|
|
|
2021-04-05 16:05:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|