ugly but works

master
howard 2021-04-12 23:41:05 -07:00
parent d88eb2845d
commit 636f8bc560
4 changed files with 523 additions and 304 deletions

View File

@ -10,8 +10,8 @@ import { setCoincident, setOrdinate } from './constraintEvents'
import { get3PtArc } from './drawArc' import { get3PtArc } from './drawArc'
import { replacer, reviver } from './utils' import { replacer, reviver } from './utils'
import { AxesHelper } from './sketchAxes' import { AxesHelper } from './sketchAxes'
import { drawDimension, _onMoveDimension, setDimLines, updateDim } from './drawDimension'; import { drawDimension, _onMoveDimension, setDimLines, updateDim, drawAngle } from './drawDimension';
import { drawAngle, _onMoveAngle, setAngLines, updateAng } from './drawAngle'; import { updateAng } from './drawAngle';
@ -131,9 +131,9 @@ class Sketch {
this.drawDimension = drawDimension.bind(this) this.drawDimension = drawDimension.bind(this)
this.drawAngle = drawAngle.bind(this) this.drawAngle = drawAngle.bind(this)
this._onMoveDimension = _onMoveDimension.bind(this) this._onMoveDimension = _onMoveDimension.bind(this)
this._onMoveAngle = _onMoveAngle.bind(this) // this._onMoveAngle = _onMoveAngle.bind(this)
this.setDimLines = setDimLines.bind(this) this.setDimLines = setDimLines.bind(this)
this.setAngLines = setAngLines.bind(this) // this.setAngLines = setAngLines.bind(this)
this.updateDim = updateDim.bind(this) this.updateDim = updateDim.bind(this)
this.updateAng = updateAng.bind(this) this.updateAng = updateAng.bind(this)
@ -223,11 +223,11 @@ class Sketch {
this.mode = "arc" this.mode = "arc"
break; break;
case 'd': case 'd':
this.drawDimension() this.drawDimension('d')
this.mode = "" this.mode = ""
break; break;
case 'q': case 'q':
this.drawAngle() this.drawDimension('a')
this.mode = "" this.mode = ""
break; break;
case 'p': case 'p':
@ -482,10 +482,10 @@ class Sketch {
} }
// this.setDimLines() this.setDimLines()
// this.setAngLines() // this.setAngLines()
this.obj3d.dispatchEvent({ type: 'change' }) // this.obj3d.dispatchEvent({ type: 'change' })
} }

View File

@ -18,97 +18,6 @@ const pointMaterial = new THREE.PointsMaterial({
const divisions = 12 const divisions = 12
export async function drawAngle() {
let selection = await this.awaitSelection({ line: 2 })
if (selection == null) return;
const line = new THREE.LineSegments(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(Array((divisions + 2) * 2 * 3).fill(-0.001), 3)
),
lineMaterial.clone()
);
const point = new THREE.Points(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(3, 3)
),
pointMaterial.clone()
)
line.userData.ids = selection.map(e => e.name)
line.layers.enable(2)
point.layers.enable(2)
let angle = getAngle(selection)
this.obj3d.children[1].add(line).add(point)
const onMove = this._onMoveAngle(point, line)
point.label = document.createElement('div');
point.label.textContent = angle.toFixed(3);
point.label.contentEditable = true;
this.labelContainer.append(point.label)
let onEnd, onKey;
let add = await new Promise((res) => {
onEnd = (e) => {
point.userData.offset = vecArr[5].toArray()
res(true)
}
onKey = (e) => e.key == 'Escape' && res(false)
this.canvas.addEventListener('pointermove', onMove)
this.canvas.addEventListener('pointerdown', onEnd)
window.addEventListener('keydown', onKey)
})
this.canvas.removeEventListener('pointermove', onMove)
this.canvas.removeEventListener('pointerdown', onEnd)
window.removeEventListener('keydown', onKey)
point.geometry.computeBoundingSphere()
line.geometry.computeBoundingSphere()
if (add) {
this.constraints.set(++this.c_id,
[
'angle', angle,
[-1, -1, selection[0].name, selection[1].name]
]
)
selection[0].userData.constraints.push(this.c_id)
selection[1].userData.constraints.push(this.c_id)
this.updateOtherBuffers()
line.name = this.c_id
line.userData.type = 'dimension'
point.name = this.c_id
point.userData.type = 'dimension'
point.label.addEventListener('focus', this.updateAng(this.c_id))
} else {
this.obj3d.children[1].children.splice(this.obj3d.children[1].length - 2, 2).forEach(
e => {
e.geometry.dispose()
e.material.dispose()
}
)
this.labelContainer.removeChild(this.labelContainer.lastChild);
sc.render()
}
return
}
export function updateAng(c_id) { export function updateAng(c_id) {
@ -136,74 +45,74 @@ export function updateAng(c_id) {
} }
let ids, _l1, _l2 // let ids, _l1, _l2
export function _onMoveAngle(point, line) { // export function _onMoveAngle(point, line) {
ids = line.userData.ids // ids = line.userData.ids
_l1 = this.obj3d.children[this.objIdx.get(ids[0])].geometry.attributes.position.array // _l1 = this.obj3d.children[this.objIdx.get(ids[0])].geometry.attributes.position.array
_l2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array // _l2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array
let loc; // let loc;
return (e) => { // return (e) => {
loc = this.getLocation(e) // loc = this.getLocation(e)
p3.set(loc.x, loc.y) // p3.set(loc.x, loc.y)
update( // update(
line.geometry.attributes.position, // line.geometry.attributes.position,
point.geometry.attributes.position, // point.geometry.attributes.position,
_l1, _l2 // _l1, _l2
) // )
// point.userData.offset = tagOffset.toArray() // save offset vector from center // // point.userData.offset = tagOffset.toArray() // save offset vector from center
// point.userData.offset = tagOffset // save offset vector from center // // point.userData.offset = tagOffset // save offset vector from center
// tagOffset = undefined // // tagOffset = undefined
sc.render() // sc.render()
} // }
} // }
export function setAngLines() { // export function setAngLines() {
const restoreLabels = this.labelContainer.childElementCount == 0; // const restoreLabels = this.labelContainer.childElementCount == 0;
const dims = this.obj3d.children[1].children // const dims = this.obj3d.children[1].children
let point, dist; // let point, dist;
for (let i = 0; i < dims.length; i += 2) { // for (let i = 0; i < dims.length; i += 2) {
// if (restoreLabels) { // // if (restoreLabels) {
// point = dims[i + 1] // point node is at i+1 // // point = dims[i + 1] // point node is at i+1
// dist = this.constraints.get(point.name)[1] // // dist = this.constraints.get(point.name)[1]
// point.label = document.createElement('div'); // // point.label = document.createElement('div');
// point.label.textContent = dist.toFixed(3); // // point.label.textContent = dist.toFixed(3);
// point.label.contentEditable = true; // // point.label.contentEditable = true;
// this.labelContainer.append(point.label) // // this.labelContainer.append(point.label)
// point.label.addEventListener('focus', this.updateAng(this.c_id)) // // point.label.addEventListener('focus', this.updateAng(this.c_id))
// } // // }
ids = dims[i].userData.ids // ids = dims[i].userData.ids
_l1 = this.obj3d.children[this.objIdx.get(ids[0])].geometry.attributes.position.array // _l1 = this.obj3d.children[this.objIdx.get(ids[0])].geometry.attributes.position.array
_l2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array // _l2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array
tagOffset = dims[i + 1].userData.offset // tagOffset = dims[i + 1].userData.offset
// p3.set(_l1[0] + tagOffset[0], _l1[1] + tagOffset[1])
// update(
// dims[i].geometry.attributes.position,
// dims[i + 1].geometry.attributes.position,
// _l1,
// _l2
// )
// }
update( // }
dims[i].geometry.attributes.position,
dims[i + 1].geometry.attributes.position,
_l1,
_l2
)
}
}
@ -271,120 +180,120 @@ const getAngle = (Obj3dLines) => {
return deltaAngle / Math.PI * 180 return deltaAngle / Math.PI * 180
} }
function update(linegeom, pointgeom, _l1, _l2) { // function update(linegeom, pointgeom, _l1, _l2) {
let i = 0; // let i = 0;
for (; i < 4;) { // for (; i < 4;) {
const arr = i == 0 ? _l1 : _l2 // const arr = i == 0 ? _l1 : _l2
vecArr[i++].set(arr[0], arr[1]) // vecArr[i++].set(arr[0], arr[1])
vecArr[i++].set(arr[3] - arr[0], arr[4] - arr[1]) // vecArr[i++].set(arr[3] - arr[0], arr[4] - arr[1])
} // }
const centerScalar = findIntersection(...vecArr.slice(0, 4)) // const centerScalar = findIntersection(...vecArr.slice(0, 4))
const center = vecArr[i++].addVectors(vecArr[0], vecArr[1].clone().multiplyScalar(centerScalar)) // const center = vecArr[4].addVectors(vecArr[0], vecArr[1].clone().multiplyScalar(centerScalar))
if (tagOffset === undefined) { // // if (tagOffset === undefined) {
vecArr[i++].subVectors(p3, center) // // vecArr[5].subVectors(p3, center)
} else { // // } else {
p3.set(center.x + tagOffset[0], center.y + tagOffset[1]) // // p3.set(center.x + tagOffset[0], center.y + tagOffset[1])
vecArr[i++].subVectors(p3, center) // // }
} // vecArr[5].subVectors(p3, center)
const tagRadius = vecArr[5].length() // const tagRadius = vecArr[5].length()
/* // /*
if tag is more than 90 deg away from midline, we shift everything by 180 // if tag is more than 90 deg away from midline, we shift everything by 180
a: array that describes absolute angular position of angle start, angle end, and tag // a: array that describes absolute angular position of angle start, angle end, and tag
a[2]: // a[2]:
tag a[1]:angle end // tag a[1]:angle end
\ | / // \ | /
\ | / // \ | /
___\|/___ a[0]+dA/2:midline // ___\|/___ a[0]+dA/2:midline
/ \ // / \
/ \ // / \
/ \ // / \
a[0]:angle start // a[0]:angle start
*/ // */
for (let j = 1, i = 0; j < vecArr.length; j += 2, i++) { // for (let j = 1, i = 0; j < vecArr.length; j += 2, i++) {
a[i] = Math.atan2(vecArr[j].y, vecArr[j].x) // a[i] = Math.atan2(vecArr[j].y, vecArr[j].x)
} // }
let dA = unreflex(a[1] - a[0]) // let dA = unreflex(a[1] - a[0])
let tagtoMidline = unreflex(a[2] - (a[0] + dA / 2)) // let tagtoMidline = unreflex(a[2] - (a[0] + dA / 2))
let shift = Math.abs(tagtoMidline) < Math.PI / 2 ? 0 : Math.PI; // let shift = Math.abs(tagtoMidline) < Math.PI / 2 ? 0 : Math.PI;
let tA1 = unreflex(a[2] - (a[0] + shift)) // let tA1 = unreflex(a[2] - (a[0] + shift))
let tA2 = unreflex(a[2] - (a[0] + dA + shift)) // let tA2 = unreflex(a[2] - (a[0] + dA + shift))
let a1, deltaAngle; // let a1, deltaAngle;
if (dA * tA1 < 0) { // if (dA * tA1 < 0) {
a1 = a[0] + tA1 + shift // a1 = a[0] + tA1 + shift
deltaAngle = dA - tA1 // deltaAngle = dA - tA1
} else if (dA * tA2 > 0) { // } else if (dA * tA2 > 0) {
a1 = a[0] + shift // a1 = a[0] + shift
deltaAngle = dA + tA2 // deltaAngle = dA + tA2
} else { // } else {
a1 = a[0] + shift // a1 = a[0] + shift
deltaAngle = dA // deltaAngle = dA
} // }
let points = linegeom.array // let points = linegeom.array
let d = 0; // let d = 0;
points[d++] = center.x + tagRadius * Math.cos(a1) // points[d++] = center.x + tagRadius * Math.cos(a1)
points[d++] = center.y + tagRadius * Math.sin(a1) // points[d++] = center.y + tagRadius * Math.sin(a1)
d++ // d++
const angle = a1 + (1 / divisions) * deltaAngle // const angle = a1 + (1 / divisions) * deltaAngle
points[d++] = center.x + tagRadius * Math.cos(angle) // points[d++] = center.x + tagRadius * Math.cos(angle)
points[d++] = center.y + tagRadius * Math.sin(angle) // points[d++] = center.y + tagRadius * Math.sin(angle)
d++ // d++
for (i = 2; i <= divisions; i++) { // for (i = 2; i <= divisions; i++) {
points[d++] = points[d - 4] // points[d++] = points[d - 4]
points[d++] = points[d - 4] // points[d++] = points[d - 4]
d++ // d++
const angle = a1 + (i / divisions) * deltaAngle // const angle = a1 + (i / divisions) * deltaAngle
points[d++] = center.x + tagRadius * Math.cos(angle) // points[d++] = center.x + tagRadius * Math.cos(angle)
points[d++] = center.y + tagRadius * Math.sin(angle) // points[d++] = center.y + tagRadius * Math.sin(angle)
d++ // d++
} // }
for (i = 0; i < 2; i++) { // for (i = 0; i < 2; i++) {
points[d++] = vecArr[2 * i].x // points[d++] = vecArr[2 * i].x
points[d++] = vecArr[2 * i].y // points[d++] = vecArr[2 * i].y
d++ // d++
points[d++] = center.x + tagRadius * Math.cos(a[i] + shift) // points[d++] = center.x + tagRadius * Math.cos(a[i] + shift)
points[d++] = center.y + tagRadius * Math.sin(a[i] + shift) // points[d++] = center.y + tagRadius * Math.sin(a[i] + shift)
d++ // d++
} // }
linegeom.needsUpdate = true; // linegeom.needsUpdate = true;
pointgeom.array.set(p3.toArray()) // pointgeom.array.set(p3.toArray())
pointgeom.needsUpdate = true; // pointgeom.needsUpdate = true;
} // }
const twoPi = Math.PI * 2 // const twoPi = Math.PI * 2
const negTwoPi = - Math.PI * 2 // const negTwoPi = - Math.PI * 2
const negPi = - Math.PI // const negPi = - Math.PI
function unreflex(angle) { // function unreflex(angle) {
if (angle > Math.PI) { // if (angle > Math.PI) {
angle = negTwoPi + angle // angle = negTwoPi + angle
} else if (angle < negPi) { // } else if (angle < negPi) {
angle = twoPi + angle // angle = twoPi + angle
} // }
return angle // return angle
} // }

View File

@ -13,22 +13,39 @@ const pointMaterial = new THREE.PointsMaterial({
}) })
export async function drawDimension() { export async function drawDimension(cc) {
let selection = await this.awaitSelection({ point: 2 }, { point: 1, line: 1 }) //////////
let selection
if (cc == 'd') {
selection = await this.awaitSelection({ point: 2 }, { point: 1, line: 1 })
} else {
selection = await this.awaitSelection({ line: 2 })
}
/////////
if (selection == null) return; if (selection == null) return;
let line;
if (cc == 'd') {
line = new THREE.LineSegments(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(Array(3 * 8).fill(-0.001), 3)
),
lineMaterial.clone()
);
} else {
line = new THREE.LineSegments(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(Array((divisions + 2) * 2 * 3).fill(-0.001), 3)
),
lineMaterial.clone()
);
}
const line = new THREE.LineSegments(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(Array(3 * 8).fill(-0.001), 3)
),
lineMaterial.clone()
);
const point = new THREE.Points( const point = new THREE.Points(
new THREE.BufferGeometry().setAttribute('position', new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(3, 3) new THREE.Float32BufferAttribute(3, 3)
@ -42,52 +59,54 @@ export async function drawDimension() {
point.layers.enable(2) point.layers.enable(2)
//////////////
let dimVal, ptLineOrder;
let dist = 0 if (cc == 'd') {
let ptLineOrder; if (selection.every(e => e.userData.type == 'point')) {
for (let i = 0; i < 3; i++) {
dimVal += (selection[0].geometry.attributes.position.array[i] - selection[1].geometry.attributes.position.array[i]) ** 2
}
if (selection.every(e => e.userData.type == 'point')) { dimVal = Math.sqrt(dimVal)
for (let i = 0; i < 3; i++) { } else {
dist += (selection[0].geometry.attributes.position.array[i] - selection[1].geometry.attributes.position.array[i]) ** 2 ptLineOrder = selection[0].userData.type == 'point' ? [0, 1] : [1, 0]
const ptArr = selection[ptLineOrder[0]].geometry.attributes.position.array
const lineArr = selection[ptLineOrder[1]].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()
disp = p3.clone().sub(p1)
proj = dir.multiplyScalar(disp.dot(dir))
perpOffset = disp.clone().sub(proj)
dimVal = Math.sqrt(perpOffset.x ** 2 + perpOffset.y ** 2)
} }
dist = Math.sqrt(dist)
} else { } else {
ptLineOrder = selection[0].userData.type == 'point' ? [0, 1] : [1, 0] dimVal = getAngle(selection)
const ptArr = selection[ptLineOrder[0]].geometry.attributes.position.array
const lineArr = selection[ptLineOrder[1]].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()
disp = p3.clone().sub(p1)
proj = dir.multiplyScalar(disp.dot(dir))
perpOffset = disp.clone().sub(proj)
dist = Math.sqrt(perpOffset.x ** 2 + perpOffset.y ** 2)
} }
////////////
this.obj3d.children[1].add(line).add(point) this.obj3d.children[1].add(line).add(point)
const onMove = this._onMoveDimension(point, line) const onMove = this._onMoveDimension(point, line)
point.label = document.createElement('div'); point.label = document.createElement('div');
point.label.textContent = dist.toFixed(3); point.label.textContent = dimVal.toFixed(3);
point.label.contentEditable = true; point.label.contentEditable = true;
this.labelContainer.append(point.label) this.labelContainer.append(point.label)
let onEnd, onKey; let onEnd, onKey;
let add = await new Promise((res) => { let add = await new Promise((res) => {
onEnd = (e) => res(true) onEnd = (e) => {
if (cc == 'd') {
point.userData.offset = hyp2.toArray() // save offset vector from hyp2
} else {
point.userData.offset = vecArr[5].toArray()
}
res(true)
}
onKey = (e) => e.key == 'Escape' && res(false) onKey = (e) => e.key == 'Escape' && res(false)
this.canvas.addEventListener('pointermove', onMove) this.canvas.addEventListener('pointermove', onMove)
@ -102,22 +121,33 @@ export async function drawDimension() {
line.geometry.computeBoundingSphere() line.geometry.computeBoundingSphere()
if (add) { if (add) {
if (ptLineOrder) { if (cc == 'd') {
this.constraints.set(++this.c_id, //??? if (ptLineOrder) {
[ this.constraints.set(++this.c_id, //???
'pt_line_distance', dist, [
[selection[ptLineOrder[0]].name, -1, selection[ptLineOrder[1]].name, -1] 'pt_line_distance', dimVal,
] [selection[ptLineOrder[0]].name, -1, selection[ptLineOrder[1]].name, -1]
) ]
)
} else {
this.constraints.set(++this.c_id, //???
[
'pt_pt_distance', dimVal,
[selection[0].name, selection[1].name, -1, -1]
]
)
}
} else { } else {
this.constraints.set(++this.c_id, //??? this.constraints.set(++this.c_id,
[ [
'pt_pt_distance', dist, 'angle', dimVal,
[selection[0].name, selection[1].name, -1, -1] [-1, -1, selection[0].name, selection[1].name]
] ]
) )
} }
selection[0].userData.constraints.push(this.c_id) selection[0].userData.constraints.push(this.c_id)
selection[1].userData.constraints.push(this.c_id) selection[1].userData.constraints.push(this.c_id)
@ -129,11 +159,9 @@ export async function drawDimension() {
point.userData.type = 'dimension' point.userData.type = 'dimension'
point.label.addEventListener('focus', this.updateDim(this.c_id)) point.label.addEventListener('focus', this.updateDim(this.c_id))
} else { } else {
this.obj3d.children[1].children.splice(this.obj3d.children[1].length - 2, 2).forEach( this.obj3d.children[1].children.splice(this.obj3d.children[1].length - 2, 2).forEach(
@ -196,16 +224,13 @@ export function _onMoveDimension(point, line) {
point.geometry.attributes.position, point.geometry.attributes.position,
_p1, _p2 _p1, _p2
) )
// console.log('heree')
console.trace()
point.userData.offset = hyp2.toArray() // save offset vector from hyp2
sc.render() sc.render()
} }
} }
export function setDimLines() { export function setDimLines() {
const restoreLabels = this.labelContainer.childElementCount == 0; const restoreLabels = this.labelContainer.childElementCount == 0;
@ -231,26 +256,29 @@ export function setDimLines() {
_p2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array _p2 = this.obj3d.children[this.objIdx.get(ids[1])].geometry.attributes.position.array
const offset = dims[i + 1].userData.offset let offset = dims[i + 1].userData.offset
if (_p1.length < _p2.length) { // corner case when p1 is pt and p2 is line
p3.set(_p1[0] + offset[0], _p1[1] + offset[1])
} else {
p3.set(_p2[0] + offset[0], _p2[1] + offset[1])
}
update( update(
dims[i].geometry.attributes.position, dims[i].geometry.attributes.position,
dims[i + 1].geometry.attributes.position, dims[i + 1].geometry.attributes.position,
_p1, _p1,
_p2 _p2,
offset
) )
} }
} }
export function onDimMoveEnd(point) {
if (hyp2) {
point.userData.offset = hyp2.toArray() // save offset vector from hyp2
} else {
point.userData.offset = vecArr[5].clone().sub(vecArr[2]).toArray()
}
}
const p1 = new THREE.Vector2() const p1 = new THREE.Vector2()
let mdpt let mdpt
const p1x = new THREE.Vector2() const p1x = new THREE.Vector2()
@ -263,7 +291,16 @@ let p1eArr, p2eArr, p3Arr
let dir, linedir, perpOffset let dir, linedir, perpOffset
let dp1e, dp2e, dp12 let dp1e, dp2e, dp12
function update(linegeom, pointgeom, _p1, _p2) { function updatex(linegeom, pointgeom, _p1, _p2, offset) {
if (offset) {
if (_p1.length < _p2.length) { // corner case when p1 is pt and p2 is line
p3.set(_p1[0] + offset[0], _p1[1] + offset[1])
} else {
p3.set(_p2[0] + offset[0], _p2[1] + offset[1])
}
}
if (_p1.length == _p2.length) { if (_p1.length == _p2.length) {
p1.set(_p1[0], _p1[1]) p1.set(_p1[0], _p1[1])
@ -352,4 +389,271 @@ function update(linegeom, pointgeom, _p1, _p2) {
} }
const divisions = 12
export function findIntersection(q, s, p, r) {
/*
Based on: https://stackoverflow.com/questions/563198/
q+s p+r
\/__________ q+u*s
/\
/ \
p q
u = (q p) × r / (r × s)
when r × s = 0, the lines are either colinear or parallel
function returns u
for "real" intersection to exist, 0<u<1
*/
const q_minus_p = q.clone().sub(p);
const r_cross_s = r.cross(s);
if (r_cross_s === 0) return null; //either colinear or parallel
return q_minus_p.cross(r) / r_cross_s;
}
const vecArr = Array(6)
for (var i = 0; i < vecArr.length; i++) vecArr[i] = new THREE.Vector2();
const a = Array(3)
function update(linegeom, pointgeom, _l1, _l2, offset) {
let i = 0;
for (; i < 4;) {
const arr = i == 0 ? _l1 : _l2
vecArr[i++].set(arr[0], arr[1])
vecArr[i++].set(arr[3] - arr[0], arr[4] - arr[1])
}
const centerScalar = findIntersection(...vecArr.slice(0, 4))
const center = vecArr[4].addVectors(vecArr[0], vecArr[1].clone().multiplyScalar(centerScalar))
if (offset) {
p3.set(center.x + offset[0], center.y + offset[1])
}
vecArr[5].subVectors(p3, center)
const tagRadius = vecArr[5].length()
/*
if tag is more than 90 deg away from midline, we shift everything by 180
a: array that describes absolute angular position of angle start, angle end, and tag
a[2]:
tag a[1]:angle end
\ | /
\ | /
___\|/___ a[0]+dA/2:midline
/ \
/ \
/ \
a[0]:angle start
*/
for (let j = 1, i = 0; j < vecArr.length; j += 2, i++) {
a[i] = Math.atan2(vecArr[j].y, vecArr[j].x)
}
let dA = unreflex(a[1] - a[0])
let tagtoMidline = unreflex(a[2] - (a[0] + dA / 2))
let shift = Math.abs(tagtoMidline) < Math.PI / 2 ? 0 : Math.PI;
let tA1 = unreflex(a[2] - (a[0] + shift))
let tA2 = unreflex(a[2] - (a[0] + dA + shift))
let a1, deltaAngle;
if (dA * tA1 < 0) {
a1 = a[0] + tA1 + shift
deltaAngle = dA - tA1
} else if (dA * tA2 > 0) {
a1 = a[0] + shift
deltaAngle = dA + tA2
} else {
a1 = a[0] + shift
deltaAngle = dA
}
let points = linegeom.array
let d = 0;
points[d++] = center.x + tagRadius * Math.cos(a1)
points[d++] = center.y + tagRadius * Math.sin(a1)
d++
const angle = a1 + (1 / divisions) * deltaAngle
points[d++] = center.x + tagRadius * Math.cos(angle)
points[d++] = center.y + tagRadius * Math.sin(angle)
d++
for (i = 2; i <= divisions; i++) {
points[d++] = points[d - 4]
points[d++] = points[d - 4]
d++
const angle = a1 + (i / divisions) * deltaAngle
points[d++] = center.x + tagRadius * Math.cos(angle)
points[d++] = center.y + tagRadius * Math.sin(angle)
d++
}
for (i = 0; i < 2; i++) {
points[d++] = vecArr[2 * i].x
points[d++] = vecArr[2 * i].y
d++
points[d++] = center.x + tagRadius * Math.cos(a[i] + shift)
points[d++] = center.y + tagRadius * Math.sin(a[i] + shift)
d++
}
linegeom.needsUpdate = true;
pointgeom.array.set(p3.toArray())
pointgeom.needsUpdate = true;
}
const twoPi = Math.PI * 2
const negTwoPi = - Math.PI * 2
const negPi = - Math.PI
function unreflex(angle) {
if (angle > Math.PI) {
angle = negTwoPi + angle
} else if (angle < negPi) {
angle = twoPi + angle
}
return angle
}
export async function drawAngle() {
/////////
let selection = await this.awaitSelection({ line: 2 })
//////////
if (selection == null) return;
const line = new THREE.LineSegments(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(Array((divisions + 2) * 2 * 3).fill(-0.001), 3)
),
lineMaterial.clone()
);
const point = new THREE.Points(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(3, 3)
),
pointMaterial.clone()
)
line.userData.ids = selection.map(e => e.name)
line.layers.enable(2)
point.layers.enable(2)
/////////////
let angle = getAngle(selection)
//////////
this.obj3d.children[1].add(line).add(point)
const onMove = this._onMoveDimension(point, line)
point.label = document.createElement('div');
point.label.textContent = angle.toFixed(3);
point.label.contentEditable = true;
this.labelContainer.append(point.label)
let onEnd, onKey;
let add = await new Promise((res) => {
onEnd = (e) => {
point.userData.offset = vecArr[5].toArray()
res(true)
}
onKey = (e) => e.key == 'Escape' && res(false)
this.canvas.addEventListener('pointermove', onMove)
this.canvas.addEventListener('pointerdown', onEnd)
window.addEventListener('keydown', onKey)
})
this.canvas.removeEventListener('pointermove', onMove)
this.canvas.removeEventListener('pointerdown', onEnd)
window.removeEventListener('keydown', onKey)
point.geometry.computeBoundingSphere()
line.geometry.computeBoundingSphere()
if (add) {
this.constraints.set(++this.c_id,
[
'angle', angle,
[-1, -1, selection[0].name, selection[1].name]
]
)
selection[0].userData.constraints.push(this.c_id)
selection[1].userData.constraints.push(this.c_id)
this.updateOtherBuffers()
line.name = this.c_id
line.userData.type = 'dimension'
point.name = this.c_id
point.userData.type = 'dimension'
point.label.addEventListener('focus', this.updateAng(this.c_id))
} else {
this.obj3d.children[1].children.splice(this.obj3d.children[1].length - 2, 2).forEach(
e => {
e.geometry.dispose()
e.material.dispose()
}
)
this.labelContainer.removeChild(this.labelContainer.lastChild);
sc.render()
}
return
}
const getAngle = (Obj3dLines) => {
for (let i = 0; i < 2; i++) {
const arr = Obj3dLines[i].geometry.attributes.position.array
vecArr[2 * i].set(...arr.slice(0, 2))
vecArr[2 * i + 1].set(arr[3] - arr[0], arr[4] - arr[1])
}
const a1 = Math.atan2(vecArr[1].y, vecArr[1].x)
const a2 = Math.atan2(vecArr[3].y, vecArr[3].x)
let deltaAngle = Math.abs(a2 - a1)
if (deltaAngle > Math.PI) {
deltaAngle = Math.PI * 2 - deltaAngle
}
return deltaAngle / Math.PI * 180
}

View File

@ -1,6 +1,6 @@
import * as THREE from '../node_modules/three/src/Three'; import * as THREE from '../node_modules/three/src/Three';
import { raycaster, color, hoverColor } from './shared'; import { raycaster, color, hoverColor } from './shared';
import { onDimMoveEnd } from './drawDimension'
let ptLoc let ptLoc
@ -156,8 +156,15 @@ export function onPick(e) {
this.obj3d.children[1].children[idx], this.obj3d.children[1].children[idx],
this.obj3d.children[1].children[idx - 1], this.obj3d.children[1].children[idx - 1],
) )
// this.onDragDim = this._onMoveAng(
// this.obj3d.children[1].children[idx],
// this.obj3d.children[1].children[idx - 1],
// )
this.canvas.addEventListener('pointermove', this.onDragDim); this.canvas.addEventListener('pointermove', this.onDragDim);
this.canvas.addEventListener('pointerup', this.onRelease) this.canvas.addEventListener('pointerup', () => {
onDimMoveEnd(this.obj3d.children[1].children[idx])
this.onRelease()
})
} }
draggedLabel = this.obj3d.children[1].children[idx].label draggedLabel = this.obj3d.children[1].children[idx].label
@ -196,7 +203,6 @@ export function onDrag(e) {
// this.objIdx.get(obj.name) * 3 // this.objIdx.get(obj.name) * 3
// ) // )
for (let x = 0; x < this.hovered.length; x++) { for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x] const obj = this.hovered[x]
this.ptsBuf.set( this.ptsBuf.set(
@ -206,7 +212,7 @@ export function onDrag(e) {
} }
this.solve() this.solve()
// this.obj3d.dispatchEvent({ type: 'change' }) this.scene.render()
} }