refactor, working delete

master
howard 2021-03-23 21:06:28 -07:00
parent c8fdfd34f8
commit e23c38c651
2 changed files with 200 additions and 118 deletions

2
dist/bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@ -10,9 +10,9 @@ function get2PtArc(p1, p2, divisions = 36) {
const dx = p2[0] - p1[0] const dx = p2[0] - p1[0]
const dy = p2[1] - p1[1] const dy = p2[1] - p1[1]
const dist = Math.sqrt(dx ** 2 + dy ** 2) const dist = Math.sqrt(dx ** 2 + dy ** 2)
const angle = (Math.atan2(dy, dx) - Math.PI / 2) % (2 * Math.PI) const midAngle = (Math.atan2(dy, dx) - Math.PI / 2) % (2 * Math.PI)
let a1 = angle - Math.PI / 6 let a1 = midAngle - Math.PI / 6
let a2 = angle + Math.PI / 6 let a2 = midAngle + Math.PI / 6
a1 = a1 < 0 ? a1 + 2 * Math.PI : a1 a1 = a1 < 0 ? a1 + 2 * Math.PI : a1
a2 = a2 < 0 ? a2 + 2 * Math.PI : a1 a2 = a2 < 0 ? a2 + 2 * Math.PI : a1
@ -32,6 +32,29 @@ function get2PtArc(p1, p2, divisions = 36) {
} }
function get3PtArc(p1, p2, c, divisions = 36) {
const v1 = [p1[0] - c[0], p1[1] - c[1]]
const v2 = [p2[0] - c[0], p2[1] - c[1]]
let a1 = Math.atan2(v1[1], v1[0])
let a2 = Math.atan2(v2[1], v2[0])
const radius = Math.sqrt(v1[0] ** 2 + v1[1] ** 2)
const deltaAngle = a2 - a1
let points = new Float32Array((divisions + 1) * 3)
for (let d = 0; d <= divisions; d++) {
const angle = a1 + (d / divisions) * deltaAngle;
points[3 * d] = c[0] + radius * Math.cos(angle);
points[3 * d + 1] = c[1] + radius * Math.sin(angle);
}
return points;
}
export class Sketcher extends THREE.Group { export class Sketcher extends THREE.Group {
constructor(camera, domElement, plane) { constructor(camera, domElement, plane) {
super() super()
@ -44,36 +67,6 @@ export class Sketcher extends THREE.Group {
this.add(new THREE.PlaneHelper(this.plane, 1, 0xffff00)); this.add(new THREE.PlaneHelper(this.plane, 1, 0xffff00));
this.pointsGroup = new THREE.Group() //0
this.add(this.pointsGroup)
this.arcPtsGroup = new THREE.Group() //1
this.add(this.arcPtsGroup)
this.linesGroup = new THREE.Group() //2
this.add(this.linesGroup)
this.arcsGroup = new THREE.Group() //3
this.add(this.arcsGroup)
this.geom = [
this.pointsGroup.children,
this.arcPtsGroup.children,
this.linesGroup.children,
this.arcsGroup.children
]
this.ptsArr = this.pointsGroup.children
this.arcPtsArr = this.arcPtsGroup.children
this.linesArr = this.linesGroup.children
this.arcsArr = this.arcsGroup.children
window.lg = this.linesArr
window.pg = this.ptsArr
this.colorPt = new THREE.Color('white') this.colorPt = new THREE.Color('white')
this.selected = new Set() this.selected = new Set()
@ -103,7 +96,6 @@ export class Sketcher extends THREE.Group {
this.raycaster.params.Line.threshold = 0.4; this.raycaster.params.Line.threshold = 0.4;
this.raycaster.params.Points.threshold = 0.2; this.raycaster.params.Points.threshold = 0.2;
this.pickThreshold = 0.1
window.addEventListener('keydown', this.onKeyPress) window.addEventListener('keydown', this.onKeyPress)
domElement.addEventListener('pointerdown', this.onPick) domElement.addEventListener('pointerdown', this.onPick)
@ -112,19 +104,36 @@ export class Sketcher extends THREE.Group {
this.mode = "" this.mode = ""
this.constraints = {} this.linkedObjs = new Map()
this.l_id = 0;
this.max_lines = 1000 this.constraints = new Map()
this.ptsBuf = new Float32Array(this.max_lines * 2) this.c_id = 0;
this.max_arcs = 1000 this.objIdx = new Map()
this.arcBuf = new Float32Array(this.max_arcs * 2 * 3)
this.max_pts = 1000
this.ptsBuf = new Float32Array(this.max_pts * 2)
this.max_links = 1000
this.linksBuf = new Int32Array(this.max_links * 5) // [0]:type, [1]:pt1, [2]:pt2, [3]:pt3, [4]:pt4
this.max_constraints = 1000 this.max_constraints = 1000
this.contraintsBuf = new Int32Array(this.max_constraints * 5) this.constraintsBuf = new Float32Array(this.max_constraints * 6) // [0]:type, [1]:pt1, [2]:pt2, [3]:lk1, [4]:lk2, [5]:val
this.contraintsValBuf = new Float32Array(this.max_constraints)
this.subsequent = false; this.subsequent = false;
this.ptsBufPt = 0;
this.endBufPt = 0;
this.linkNum = {
'line': 0,
'arc': 1
}
this.contraintNum = {
'coincident': 0,
'parallel': 1
}
} }
orientSketcher() { orientSketcher() {
@ -154,7 +163,7 @@ export class Sketcher extends THREE.Group {
this.mode = "arc" this.mode = "arc"
break; break;
case 'd': case 'd':
this.delete() this.deleteSelected()
break; break;
case '=': case '=':
this.plane.applyMatrix4(new Matrix4().makeRotationY(0.1)) this.plane.applyMatrix4(new Matrix4().makeRotationY(0.1))
@ -184,15 +193,14 @@ export class Sketcher extends THREE.Group {
), ),
this.camera this.camera
); );
const hoverPts = this.raycaster.intersectObjects(this.ptsArr)
// const hoverPts = this.raycaster.intersectObjects(this.arcPtsArr) const hoverPts = this.raycaster.intersectObjects(this.children)
if (hoverPts.length) { if (hoverPts.length) {
let minDist = hoverPts[0].distanceToRay let minDist = Infinity;
let idx = 0 let idx = 0
for (let i = 0; i < hoverPts.length; i++) {
for (let i = 1; i < hoverPts.length; i++) { if (hoverPts[i].distanceToRay && hoverPts[i].distanceToRay <= minDist) {
if (hoverPts[i].distanceToRay <= minDist) {
minDist = hoverPts[i].distanceToRay minDist = hoverPts[i].distanceToRay
idx = i idx = i
} }
@ -204,13 +212,6 @@ export class Sketcher extends THREE.Group {
return return
} }
// const hoverLines = this.raycaster.intersectObjects(this.linesArr)
// if (hoverLines.length) {
// hoverLines[0].object.material.color.set(0xff0000)
// this.hovered = hoverLines[0].object
// this.dispatchEvent({ type: 'change' })
// return
// }
if (this.hovered) { if (this.hovered) {
this.hovered = null; this.hovered = null;
@ -227,7 +228,7 @@ export class Sketcher extends THREE.Group {
if (this.hovered) { if (this.hovered) {
this.selected.add(this.hovered) this.selected.add(this.hovered)
if (this.hovered.type === "Points") { if (this.hovered.type === "Points") {
this.grabPtIdx = this.ptsArr.indexOf( this.grabPtIdx = this.children.indexOf(
this.hovered this.hovered
) )
this.domElement.addEventListener('pointermove', this.onDrag); this.domElement.addEventListener('pointermove', this.onDrag);
@ -244,7 +245,7 @@ export class Sketcher extends THREE.Group {
onDrag(e) { onDrag(e) {
const mouseLoc = this.getLocation(e); const mouseLoc = this.getLocation(e);
this.ptsArr[this.grabPtIdx].geometry.attributes.position.set(mouseLoc); this.children[this.grabPtIdx].geometry.attributes.position.set(mouseLoc);
this.solve() this.solve()
this.dispatchEvent({ type: 'change' }) this.dispatchEvent({ type: 'change' })
} }
@ -253,51 +254,98 @@ export class Sketcher extends THREE.Group {
onRelease() { onRelease() {
this.domElement.removeEventListener('pointermove', this.onDrag) this.domElement.removeEventListener('pointermove', this.onDrag)
this.domElement.removeEventListener('pointerup', this.onRelease) this.domElement.removeEventListener('pointerup', this.onRelease)
this.ptsArr[this.grabPtIdx].geometry.computeBoundingSphere() this.children[this.grabPtIdx].geometry.computeBoundingSphere()
// this.grabbedObject = null // this.grabbedObject = null
} }
delete() { deleteSelected() {
const deleteArr = [] let minI = this.children.length;
for (let obj of this.selected) { for (let obj of this.selected) {
const idx = obj.parent.children.indexOf(obj) minI = Math.min(minI, this.delete(obj))
if (obj.parent == this.linesGroup) {
deleteArr.push([2, idx])
deleteArr.push([0, idx * 2])
deleteArr.push([0, idx * 2 + 1])
} else if (obj.parent == this.pointsGroup) {
deleteArr.push([0, idx])
deleteArr.push([0, idx + (idx % 2 == 0 ? 1 : -1)])
deleteArr.push([2, Math.floor(idx / 2)])
} else if (obj.parent == this.arcsGroup) {
} else if (obj.parent == this.arcPtsGroup) {
} }
}
deleteArr.sort((a, b) => a[0] == b[0] ? b[1] - a[1] : b[0] - a[0]); this.updateBuffer(minI)
this.resetConstraints()
let li, idx;
for (let i = 0; i < deleteArr.length; i++) {
if (deleteArr[i][0] == li && deleteArr[i][1] == idx) {
continue
} else {
[li, idx] = deleteArr[i]
}
const obj = this.geom[li][idx]
obj.geometry.dispose()
obj.material.dispose()
obj.parent.children.splice(idx, 1)
obj.parent = null;
}
this.selected.clear() this.selected.clear()
this.dispatchEvent({ type: 'change' }) this.dispatchEvent({ type: 'change' })
} }
deleteConstraints(c_id) {
for (let ob of this.constraints.get(c_id)[0]) {
if (ob == -1) continue
ob.constraints.delete(c_id)
}
this.constraints.delete(c_id)
}
resetConstraints() {
let i = 0
for (let [key,obj] of this.constraints) {
this.constraintsBuf.set(
[
...obj[0].map(ele => this.objIdx.get(ele.id) || -1),
this.contraintNum[obj[4]], obj[5]
],
(i) * 6
)
i++
}
i = 0;
for (let [key,obj] of this.linkedObjs) {
this.linksBuf.set(
[
...obj[0].map(ele => this.objIdx.get(ele.id) || -1),
this.linkNum[obj[4]]
],
(i) * 5
)
i++
}
}
delete(obj) {
const link = this.linkedObjs.get(obj.l_id)
let i = this.children.indexOf(link[0][0])
if (i == -1) return Infinity
for (let j = 0; j < link[0].length; j++) {
const obj = this.children[i + j]
obj.geometry.dispose()
obj.material.dispose()
for (let c_id of obj.constraints) {
this.deleteConstraints(c_id)
}
}
this.children.splice(i, link[0].length)
this.linkedObjs.delete(obj.l_id)
return i
}
updateBuffer(startingIdx) {
for (let i = startingIdx; i < this.children.length; i++) {
const obj = this.children[i]
this.objIdx.set(obj.id, i)
if (obj.type == "Points") {
this.ptsBuf[2 * i] = obj.geometry.attributes.position.array[0]
this.ptsBuf[2 * i + 1] = obj.geometry.attributes.position.array[1]
}
}
}
clear() { clear() {
if (this.mode == "") return if (this.mode == "") return
@ -306,13 +354,7 @@ export class Sketcher extends THREE.Group {
this.domElement.removeEventListener('pointermove', this.beforeClick_2); this.domElement.removeEventListener('pointermove', this.beforeClick_2);
this.domElement.removeEventListener('pointerdown', this.onClick_2); this.domElement.removeEventListener('pointerdown', this.onClick_2);
const lastLine = this.linesArr[this.linesArr.length - 1] this.delete(this.children[this.children.length - 1])
this.linesGroup.remove(lastLine)
lastLine.geometry.dispose()
const lastPoints = this.ptsArr.slice(this.ptsArr.length - 2)
this.pointsGroup.remove(...lastPoints)
lastPoints.forEach(obj => obj.geometry.dispose())
this.dispatchEvent({ type: 'change' }) this.dispatchEvent({ type: 'change' })
this.subsequent = false this.subsequent = false
@ -342,13 +384,7 @@ export class Sketcher extends THREE.Group {
new THREE.PointsMaterial().copy(this.pointMaterial) new THREE.PointsMaterial().copy(this.pointMaterial)
); );
this.p1.matrixAutoUpdate = false; this.p1.matrixAutoUpdate = false;
this.p1.constraints = new Set()
if (this.subsequent) {
// this.constraints[constraint++] = [
// [this.ptsArr[this.ptsArr.length-1], this.p1]
// ]
}
this.p2Geom = new THREE.BufferGeometry().setAttribute('position', this.p2Geom = new THREE.BufferGeometry().setAttribute('position',
new THREE.BufferAttribute(new Float32Array(3), 3) new THREE.BufferAttribute(new Float32Array(3), 3)
@ -358,6 +394,9 @@ export class Sketcher extends THREE.Group {
new THREE.PointsMaterial().copy(this.pointMaterial) new THREE.PointsMaterial().copy(this.pointMaterial)
); );
this.p2.matrixAutoUpdate = false; this.p2.matrixAutoUpdate = false;
this.p2.constraints = new Set()
let toPush;
if (this.mode == "line") { if (this.mode == "line") {
this.lineGeom = new THREE.BufferGeometry().setAttribute('position', this.lineGeom = new THREE.BufferGeometry().setAttribute('position',
@ -367,12 +406,33 @@ export class Sketcher extends THREE.Group {
this.line = new THREE.Line(this.lineGeom, this.line = new THREE.Line(this.lineGeom,
new THREE.LineBasicMaterial().copy(this.lineMaterial) new THREE.LineBasicMaterial().copy(this.lineMaterial)
); );
this.line.constraints = new Set()
this.line.frustumCulled = false; this.line.frustumCulled = false;
toPush = [this.p1, this.p2, this.line];
if (this.subsequent) {
this.constraintsBuf.set(
[
this.children.length - 2, this.children.length, -1, -1,
this.contraintNum['coincident'], -1
],
(this.constraints.size) * 6
)
this.constraints.set(this.c_id,
[
[this.children[this.children.length - 2], this.p1, -1, -1],
'coincident', -1
]
)
this.p1.constraints.add(this.c_id)
this.children[this.children.length - 2].constraints.add(this.c_id)
this.c_id += 1
}
this.linesGroup.add(this.line)
this.pointsGroup.add(this.p1)
this.pointsGroup.add(this.p2)
} else if (this.mode == "arc") { } else if (this.mode == "arc") {
this.arcGeom = new THREE.BufferGeometry().setAttribute('position', this.arcGeom = new THREE.BufferGeometry().setAttribute('position',
@ -391,14 +451,34 @@ export class Sketcher extends THREE.Group {
new THREE.PointsMaterial().copy(this.pointMaterial) new THREE.PointsMaterial().copy(this.pointMaterial)
); );
this.arcsGroup.add(this.arc) toPush = [this.p1, this.p2, this.p3, this.arc]
this.arcPtsGroup.add(this.p1)
this.arcPtsGroup.add(this.p2)
this.arcPtsGroup.add(this.p3)
} }
let ptr = this.children.length
this.add(...toPush)
this.updateBuffer(ptr)
const link_entry = new Array(5).fill(-1)
for (let i = ptr, j = 0; j < toPush.length - 1;) {
link_entry[j++] = i++
}
link_entry[link_entry.length - 1] = this.linkNum[this.mode]
this.linksBuf.set(
link_entry,
(this.linkedObjs.size) * 5
)
this.linkedObjs.set(this.l_id, [toPush, this.mode])
for (let obj of toPush) {
obj.l_id = this.l_id
}
this.l_id += 1
this.domElement.removeEventListener('pointerdown', this.onClick_1) this.domElement.removeEventListener('pointerdown', this.onClick_1)
this.domElement.addEventListener('pointermove', this.beforeClick_2) this.domElement.addEventListener('pointermove', this.beforeClick_2)
@ -456,27 +536,29 @@ export class Sketcher extends THREE.Group {
this.p3Geom.computeBoundingSphere() this.p3Geom.computeBoundingSphere()
} }
solve() { solve() {
for (let i = 0, p = 0; i < this.ptsArr.length; i++) { for (let i = 0, p = 0; i < this.children.length; i++) {
this.ptsBuf[p++] = this.ptsArr[i].geometry.attributes.position.array[0] this.ptsBuf[p++] = this.children[i].geometry.attributes.position.array[0]
this.ptsBuf[p++] = this.ptsArr[i].geometry.attributes.position.array[1] this.ptsBuf[p++] = this.children[i].geometry.attributes.position.array[1]
} }
buffer = Module._malloc(this.ptsBuf.length * this.ptsBuf.BYTES_PER_ELEMENT) buffer = Module._malloc(this.ptsBuf.length * this.ptsBuf.BYTES_PER_ELEMENT)
Module.HEAPF32.set(this.ptsBuf, buffer >> 2) Module.HEAPF32.set(this.ptsBuf, buffer >> 2)
Module["_solver"](this.ptsArr.length / 2, buffer) Module["_solver"](this.children.length / 2, buffer)
let ptr = buffer >> 2; let ptr = buffer >> 2;
for (let i = 0; i < this.ptsArr.length * 2; i += 4) { for (let i = 0; i < this.linkedObjs.lengthxx; i += 1) {
const pt1_pos = this.ptsArr[i >> 1].geometry.attributes.position;
const pt2_pos = this.ptsArr[(i >> 1) + 1].geometry.attributes.position; const pt1_pos = this.children[i >> 1].geometry.attributes.position;
const pt2_pos = this.children[(i >> 1) + 1].geometry.attributes.position;
const line_pos = this.linesArr[i >> 2].geometry.attributes.position; const line_pos = this.linesArr[i >> 2].geometry.attributes.position;
pt1_pos.array[0] = Module.HEAPF32[ptr] pt1_pos.array[0] = Module.HEAPF32[ptr]