在JavaScript中剪切矩形
Clipping a Rectangle in JavaScript
本文关键字:JavaScript 更新时间:2023-09-26
我想写一个函数,它需要两个重叠的矩形,并返回一个矩形数组,覆盖矩形a的面积,但不包括矩形b的面积。我很难弄清楚这个算法是什么样子的,因为可能的碰撞数量是巨大的,很难解释。
tl;dr我正在尝试使用另一个矩形剪切一个矩形,结果是一个矩形的集合覆盖了剩余的区域。
|-------------| |-------------|
|A | |R1 |
| |-------|----| |-----|-------|
| |B | | To |R2 |
| | | | ====> | |
| | | | | |
|-----|-------| | |-----|
| |
|------------|
POSSIBLE OVERLAP PATTERNS
|-----| |-----| |-----| |-----|
| |---|-| |-|---| | | |-| | | |-| |
|-|---| | | |---|-| |-|-|-| | |-| |
|-----| |-----| |-| |-----|
|-| |-----| |-----|
|-|-|-| | |---|-| |-|---| |
| |-| | | |---|-| |-|---| |
|-----| |-----| |-----|
请注意,可能的重叠模式是所示的两倍,因为矩形A和B可以是上述任何重叠模式中的任何一个矩形
这两个矩形将屏幕划分为9个区域(不是14个)。再考虑一下你的配置:
y1 -> |-------------|
|A |
y2 -> | |-------|----|
| |B | |
| | | |
| | | |
y3 -> |-----|-------| |
| |
y4 -> |------------|
^ ^ ^ ^
x1 x2 x3 x4
x坐标定义了5个垂直波段,但是第一个(左)和最后一个(右)是无趣的,所以你只需要在从x1到x4的3个波段上工作。y坐标也一样:从y1到y4的三个水平带。
所以这是9个矩形区域,它们属于A, B,不属于B,或者两者都属于。您的示例是这样划分的:
|-----|-------|----|
|A |A |none|
|-----|-------|----|
|A |Both |B |
| | | |
| | | |
|-----|-------|----|
|none |B |B |
|-----|-------|----|
所以比较A和B的坐标,你会发现9个区域中哪一个只属于A,它们是要保留的区域。
对于任何特定的设置都不会有唯一的解决方案,但您可以使用此算法轻松找到其中一个解决方案:
- 在a中找到一个矩形B之上的矩形。如果a的顶部高于B(即px值较低),则存在这样一个矩形。这个矩形由:(A的左边缘,A的上边缘)到(A的右边缘,B的上边缘)来定义。
- 如果B的左边缘在A的左边缘的右边,则下一个矩形为:(A的左边缘,min(A的上边缘,B的上边缘))到(B的左边缘,max (A的下边缘,B的下边缘))
- 如果B的右边缘在B的右边缘的左边,同上面
- …以及B 下面可能的矩形
总的来说,你将得到0到4个矩形。
伪代码带有一个有点不寻常的,但为了这个目的很清楚的定义:
function getClipped(A, B) {
var rectangles = [];
if (A.top < B.top) {
rectangles.push({ left: A.left, top: A.top, right: A.right, bottom: B.top });
}
if (A.left < B.left) {
rectangles.push({ left: A.left, top: max(A.top, B.top), right: B.left, bottom: min(A.bottom, B.bottom) });
}
if (A.right > B.right) {
rectangles.push({ left: B.right, top: max(A.top, B.top), right: A.right, bottom: min(A.bottom, B.bottom) });
}
if (A.bottom > B.bottom) {
rectangles.push({ left: A.left, top: B.bottom, right: A.right, bottom. A.bottom });
}
return rectangles;
}
var rectA = { left: nn, top: nn, right: nn, bottom: nn};
var rectB = { left: nn, top: nn, right: nn, bottom: nn};
var clipped = getClipped(rectA, rectB) ;
从dan开始。P的代码,使用boisvert的建议,我的例程看起来像这样:
this.clip = function(other) {
var res = [];
// Rect has a constructor accepting (left, top, [right, bottom]) for historical reasons
if (this.top < other.top) {
res.push(new Rect(Math.max(this.left, other.left), other.top, [Math.min(this.right, other.right), this.top]));
}
if (this.left > other.left) {
res.push(new Rect(other.left, other.top, [this.left, other.bot]));
}
if (this.right < other.right) {
res.push(new Rect(this.right, other.top, [other.right, other.bot]));
}
if (this.bot > other.bot) {
res.push(new Rect(Math.max(this.left, other.left), this.bot, [Math.min(this.right, other.right), other.bot]));
}
return res;
}
我测试了16个案例(4个独立的if)。
相关文章:
- 为什么不't Javascript对我的输入值进行了一些重新检查
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 将函数的上下文应用于javascript变量
- 使用php或javascript从facebook相册URL中删除多余的部分
- 正在添加'X'按钮,在文本字段旁边使用javascript
- 如何在JavaScript中将字符串转换为函数引用
- 模糊事件的Javascript测试
- Javascript更改图标
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- 如何使用WCF服务和javascript表单post上传.doc文件
- javascript结合了数组和字典
- 这是什么 ==- javascript 运算符
- 从javascript创建一个列表
- 无法在通过jQuery的ajax加载的页面中执行javascript
- Javascript:selenium Web驱动程序isDisplayed()不工作
- 如何通过ajax刷新JSF填充的javascript变量
- 如何在Javascript中将JSon对象转换为数组
- Javascript生成的表单未提交
- 使用javascript将动态表从一个html页面打印到另一个html页
- 通过javascript重定向html传递php变量