UNPKG

aha-graphic

Version:

Graphic Tools

197 lines (175 loc) 6.35 kB
// MIT License // Copyright (c) 2020 FredDon // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. class Rect { constructor(x, y, width, height) { if (arguments[0] instanceof Rect) { let rect = arguments[0]; this.x = rect.x; this.y = rect.y; this.width = rect.width; this.height = rect.height; } else { this.x = x; this.y = y; this.width = width; this.height = height; } } mapToRectF() { return new RectF(this.x, this.y, this.x + this.width, this.y + this.height); } } class RectF { constructor(left, top, right, bottom) { if (arguments[0] instanceof RectF) { let rectF = arguments[0]; this.left = rectF.left; this.top = rectF.top; this.right = rectF.right; this.bottom = rectF.bottom; } else { this.left = left; this.top = top; this.right = right; this.bottom = bottom; } } mapToRect() { let width = this.width(), height = this.height(); return new Rect(this.left, this.top, width, height); } isEmpty() { return this.left >= this.right || this.top >= this.bottom; } width() { return this.right - this.left; } /** * @return the rectangle's height. This does not check for a valid rectangle * (i.e. top <= bottom) so the result may be negative. */ height() { return this.bottom - this.top; } /** * @return the horizontal center of the rectangle. This does not check for * a valid rectangle (i.e. left <= right) */ centerX() { return (this.left + this.right) * 0.5; } /** * @return the vertical center of the rectangle. This does not check for * a valid rectangle (i.e. top <= bottom) */ centerY() { return (this.top + this.bottom) * 0.5; } /** * Set the rectangle to (0,0,0,0) */ setEmpty() { this.left = this.right = this.top = this.bottom = 0; } /** * Offset the rectangle by adding dx to its left and right coordinates, and * adding dy to its top and bottom coordinates. * * @param dx The amount to add to the rectangle's left and right coordinates * @param dy The amount to add to the rectangle's top and bottom coordinates */ offset(dx, dy) { this.left += dx; this.top += dy; this.right += dx; this.bottom += dy; } /** * Offset the rectangle to a specific (left, top) position, * keeping its width and height the same. * * @param newLeft The new "left" coordinate for the rectangle * @param newTop The new "top" coordinate for the rectangle */ offsetTo(newLeft, newTop) { this.right += newLeft - this.left; this.bottom += newTop - this.top; this.left = newLeft; this.top = newTop; } /** * Returns true if (x,y) is inside the rectangle. The left and top are * considered to be inside, while the right and bottom are not. This means * that for a x,y to be contained: left <= x < right and top <= y < bottom. * An empty rectangle never contains any point. * * @param x The X coordinate of the point being tested for containment * @param y The Y coordinate of the point being tested for containment * @return true iff (x,y) are contained by the rectangle, where containment * means left <= x < right and top <= y < bottom */ contains(x, y) { return this.left < this.right && this.top < this.bottom // check for empty first && x >= this.left && x < this.right && y >= this.top && y < this.bottom; } /** * Returns true iff the 4 specified sides of a rectangle are inside or equal * to this rectangle. i.e. is this rectangle a superset of the specified * rectangle. An empty rectangle never contains another rectangle. * * @param left The left side of the rectangle being tested for containment * @param top The top of the rectangle being tested for containment * @param right The right side of the rectangle being tested for containment * @param bottom The bottom of the rectangle being tested for containment * @return true iff the the 4 specified sides of a rectangle are inside or * equal to this rectangle */ contains4p(left, top, right, bottom) { // check for empty first return this.left < this.right && this.top < this.bottom // now check for containment && this.left <= left && this.top <= top && this.right >= right && this.bottom >= bottom; } /** * Returns true iff the specified rectangle r is inside or equal to this * rectangle. An empty rectangle never contains another rectangle. * * @param r The rectangle being tested for containment. * @return true iff the specified rectangle r is inside or equal to this * rectangle */ containsRectF(r) { // check for empty first return this.left < this.right && this.top < this.bottom // now check for containment && this.left <= r.left && this.top <= r.top && this.right >= r.right && this.bottom >= r.bottom; } /** * Scales up the rect by the given scale. */ scale(scale) { if (scale != 1.0) { this.left = this.left * scale; this.top = this.top * scale; this.right = this.right * scale; this.bottom = this.bottom * scale; } } } export { Rect, RectF };