1/* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import {Point} from './point'; 18 19/** 20 * A rectangle class in 2D space. 21 */ 22export class Rect { 23 constructor( 24 readonly x: number, 25 readonly y: number, 26 readonly w: number, 27 readonly h: number, 28 ) {} 29 30 isAlmostEqual(other: Rect, eps: number): boolean { 31 const isClose = (a: number, b: number) => Math.abs(a - b) <= eps; 32 return ( 33 isClose(this.x, other.x) && 34 isClose(this.y, other.y) && 35 isClose(this.w, other.w) && 36 isClose(this.h, other.h) 37 ); 38 } 39 40 containsPoint(point: Point): boolean { 41 return ( 42 this.x <= point.x && 43 point.x <= this.x + this.w && 44 this.y <= point.y && 45 point.y <= this.y + this.h 46 ); 47 } 48 49 cropRect(other: Rect): Rect { 50 const maxLeft = Math.max(this.x, other.x); 51 const minRight = Math.min(this.x + this.w, other.x + other.w); 52 const maxTop = Math.max(this.y, other.y); 53 const minBottom = Math.min(this.y + this.h, other.y + other.h); 54 return new Rect(maxLeft, maxTop, minRight - maxLeft, minBottom - maxTop); 55 } 56 57 containsRect(other: Rect): boolean { 58 return ( 59 this.w > 0 && 60 this.h > 0 && 61 this.x <= other.x && 62 this.y <= other.y && 63 this.x + this.w >= other.x + other.w && 64 this.y + this.h >= other.y + other.h 65 ); 66 } 67 68 intersectsRect(other: Rect): boolean { 69 if ( 70 this.x < other.x + other.w && 71 other.x < this.x + this.w && 72 this.y <= other.y + other.h && 73 other.y <= this.y + this.h 74 ) { 75 let [x, y, w, h] = [this.x, this.y, this.w, this.h]; 76 77 if (this.x < other.x) { 78 x = other.x; 79 } 80 if (this.y < other.y) { 81 y = other.y; 82 } 83 if (this.x + this.w > other.x + other.w) { 84 w = other.w; 85 } 86 if (this.y + this.h > other.y + other.h) { 87 h = other.h; 88 } 89 90 return !new Rect(x, y, w, h).isEmpty(); 91 } 92 93 return false; 94 } 95 96 isEmpty(): boolean { 97 const [x, y, w, h] = [this.x, this.y, this.w, this.h]; 98 const nullValuePresent = 99 x === -1 || y === -1 || x + w === -1 || y + h === -1; 100 const nullHeightOrWidth = w <= 0 || h <= 0; 101 return nullValuePresent || nullHeightOrWidth; 102 } 103} 104