球範圍選擇,指的是以滑鼠點選的位置為中心點,一定半徑內的所有網格點資訊,這種方法可以用來模擬圓形的筆刷,接觸到三維空間中的物體表面。
首先改寫 Editor 的 mouseDown 函數,先複製先前的找最接近點的功能,並且定義想找尋的球半徑。
var radius = 1.5;
var intersected = self.viewer.intersects[0];
if (intersected.object.skip) return;
var topology = intersected.object.topology;
var vertices = self.getVertices();
var nearest = self.getNearest(vertices, intersected.point);
接著在 Editor 建立一個 circleSelect 函數用來求取範圍內選擇的點,此函數包含三個引數 目標點、搜尋半徑、點的清單,並且在內部先宣告必要的基本參數,以及在 selectedIDs 中放入目標點。
Editor.prototype.circleSelect = function (point, radius, selectedIDs) {
var self = this;
var intersected = self.viewer.intersects[0];
var topology = intersected.object.topology;
if(!selectedIDs) selectedIDs = [];
selectedIDs.push(point.ID);
// Do Something
return selectedIDs;
};
然後建立兩個迴圈,第一層迴圈內利用的目標頂點的邊拓樸關係找到鄰近的的點群,第二層迴圈則查詢這些點的是否不在 點的清單 內。
var i = 0;
var j = 0;
var edgeIDs = point.edgeIDs;
for(i=0;i<edgeIDs.length;i++) {
var edgeID = edgeIDs[i];
var edge = topology.edge[edgeID];
var vertexIDs = edge.vertexIDs;
for(j=0;j<vertexIDs.length;j++) {
var vertexID = vertexIDs[j];
if(selectedIDs.indexOf(vertexID) === -1) {
// Do Something
}
}
}
最後計算頂點距離是否小於半徑,是的話就從該點繼續進行反覆查找的動作直到結束。
var vector = topology.vertex[vertexID];
var distance = intersected.point.distanceTo(vector.vector3);
if(distance < radius) {
self.circleSelect(vector, radius, selectedIDs);
}
回到 mouseDown 函數,呼叫 circleSelect 函數取得球範圍內的點,並且畫幾顆球做顯示,效果如下圖。
var selectedIDs = self.circleSelect(nearest, radius);
var i = 0;
for(i=0;i<selectedIDs.length;i++) {
var selectedID = selectedIDs[i];
var selected = topology.vertex[selectedID];
var geometry = new THREE.SphereBufferGeometry(0.1, 16, 16);
var material = new THREE.MeshPhongMaterial({
color: 0xff0000
});
var mesh = new THREE.Mesh(geometry, material);
mesh.skip = true;
mesh.position.copy(selected.vector3);
self.viewer.scene.add(mesh);
self.viewer.meshs.push(mesh);
}
在球模型 SphereD10Binary.STL 進行球範圍選擇頂點
https://github.com/QQBoxy/threecad/tree/master/models
https://qqboxy.github.io/threecad/public/example20.html
https://github.com/QQBoxy/threecad/blob/master/client/example20/Editor.js
本次先預備好球範圍選擇功能,會應用到後續的功能中,其採用了較簡易的計算方式相信大家都能吸收良好。另外除了使用邊拓樸以外也可以使用面拓樸來搜尋,若需要更準確且效率高的方法,必須另外建立網格碰撞及模型搜尋的樹狀結構關係,而本文僅就基礎說明就不再深入了。