如何用直线切割多边形?Paper.js+Canvas游戏开发技术问询
解决Paper.js中沿任意直线分割凸多边形的问题
你当前的代码能检测到多边形与分割线的交点,但分割后无法得到正确的闭合多边形,核心问题出在Path对象的复制方式、分割顺序处理以及交点排序上。
原代码的关键问题
- 用
Object.assign(p1)复制Paper.js的Path对象无效:Paper.js的Path是带有内部状态的复杂对象,浅拷贝会丢失关键属性,必须用clone()方法 - 未对交点排序:直接按交点数组顺序分割,可能导致分割顺序错误,生成无效形状
- 分割对象引用错误:第二次分割的对象应该是第一次分割后的剩余路径,而非原路径
修正后的完整代码
// 初始化凸多边形 var polygon = new Path.RegularPolygon(new Point(200, 300), 4, 100); polygon.strokeColor = 'blue'; polygon.fullySelected = true; var shapesArray = [polygon]; var myPath; function splitShape(targetShapes, cutLine) { var updatedShapes = []; targetShapes.forEach(function(shape) { var intersections = shape.getIntersections(cutLine); // 凸多边形与直线最多有2个交点,确保有效分割条件 if (intersections.length === 2) { // 获取交点在多边形路径上的位置对象 var loc1 = shape.getNearestLocation(intersections[0].point); var loc2 = shape.getNearestLocation(intersections[1].point); // 按路径偏移量排序交点,保证分割顺序正确 if (loc1.offset > loc2.offset) { [loc1, loc2] = [loc2, loc1]; } // 第一次分割得到第一个子路径 var part1 = shape.split(loc1); // 第二次分割剩余路径得到第二个子路径 var part2 = shape.split(loc2); // 确保子路径为闭合多边形 part1.closed = true; part2.closed = true; // 用clone()复制路径,避免引用冲突 updatedShapes.push(part1.clone()); updatedShapes.push(part2.clone()); // 移除原路径,清理画布 shape.remove(); } else { // 无交点时保留原形状 updatedShapes.push(shape.clone()); } }); // 更新全局形状数组 shapesArray = updatedShapes; cutLine.remove(); // 直接移除分割线,替代隐藏操作 } // 鼠标绘制分割线事件 function onMouseDown(event) { myPath = new Path(); myPath.strokeColor = 'black'; myPath.add(event.point); } function onMouseDrag(event) { myPath.segments.pop(); myPath.add(event.point); } function onMouseUp(event) { splitShape(shapesArray, myPath); }
关键修改说明
- Path对象复制:使用
clone()方法完整复制Paper.js Path的所有属性和内部状态,避免浅拷贝导致的异常 - 交点排序:通过比较交点在路径上的
offset值,确保分割顺序符合多边形的路径走向,生成正确的闭合子多边形 - 分割逻辑优化:第一次分割后,原路径自动变为剩余部分,第二次分割直接操作该剩余路径,确保得到两个完整的子形状
- 画布清理:分割完成后移除原多边形和分割线,避免画布上残留无效元素
内容的提问来源于stack exchange,提问作者DYM
相关产品推荐
相关产品推荐

