我正在制作地形编辑器,我需要找到一组点的周边多边形。如果我只需要一个凸壳,那么速度就没问题了。为了制造一个凹形船体,我必须经历一些箍。我已经发现我可以对点进行三角测量,然后扔掉任何三角形,其边长比点之间的距离已知。
下一步是问题:使用JSTS几何库(http://github.com/bjornharrtell/jsts)将三角形(作为迷你多边形)组合成一个大的多边形非常慢。
请参阅完整代码:http://codepen.io/anon/pen/oCfDh
我有一个数组(多边形)被合并以形成最终的多边形。问题是552点(我想支持15k +),运行需要~3500ms。查看codepen链接中的控制台,了解您的速度。
var reader = new jsts.io.WKTReader(),
merged = reader.read(polys[0]).union(reader.read(polys[1]));
console.time('jsts mergization');
for(var i = 2; i<polys.length; i++){
try{
merged = merged.union(reader.read(polys[i]));
}catch(err){
console.log('Error triangulating points!');
};
};
console.timeEnd('jsts mergization');
是否有人知道将三角形合并为多边形或更宽的方式以及以一种完全不同的方式从一组点构建凹多边形的更快方法?
答案 0 :(得分:0)
谢谢simonzack!
我已经使用你的建议改写了算法,而且速度要快得多!
重做的代码:http://codepen.io/anon/pen/Btdyj
同样的例子现在运行〜15ms!
function pointsToPolygon(points, triangles, maxEdgeLength){
console.time('homebrewed mergization');
var dist = function(a, b){
if(typeof a === "number"){
a = points[a];
};
if(typeof b === "number"){
b = points[b];
};
return Math.sqrt(Math.pow(a[0] - b[0], 2) +
Math.pow(a[1] - b[1], 2));
};
if(!points.length){
return undefined;
};
var pointFreq = [];
points.forEach(function(v){
pointFreq.push(0);
});
for(var i = triangles.length; i; i-=3){
if(dist(triangles[i-1], triangles[i-2]) < maxEdgeLength &&
dist(triangles[i-3], triangles[i-2]) < maxEdgeLength &&
dist(triangles[i-1], triangles[i-3]) < maxEdgeLength){
pointFreq[triangles[i-1]]++;
pointFreq[triangles[i-2]]++;
pointFreq[triangles[i-3]]++;
};
};
// Keep points that are used in 3 or fewer triangles
var output =[];
pointFreq.forEach(function(freq, i){
if(freq<4){
output.push(points[i]);
};
});
// Sort points by looping around by each next closest point
var sorted = [];
while(output.length>0){
sorted.push(output.pop());
output=output.sort(function(a,b){
var distA =dist(sorted[sorted.length-1], a),
distB =dist(sorted[sorted.length-1], b);
if(distA < distB){
return 1;
}else if(distA === distB){
return 0;
};
return -1;
});
};
sorted=simplifyPath(sorted,0.1);
console.timeEnd('homebrewed mergization');
return sorted;
};
我可以通过过滤3个或更少三角形中使用的点来找到边界,然后通过从任意点的每个下一个最近点循环来对点进行排序。
由于Douglas-Peucker简化算法(改编自https://gist.github.com/adammiller/826148),可能不是100%准确,但对我来说似乎已经足够了。