@aurigma/design-atoms-model
Version:
Design Atoms is a part of Customer's Canvas SDK which allows for manipulating individual design elements through your code.
222 lines • 8.82 kB
JavaScript
import { PointF } from "./PointF";
import { EqualsOfFloatNumbers } from "./Common";
import { Matrix } from "./Matrix";
import { ArgumentException } from "../Exception";
import { EventWithSenderArg } from "../EventObject";
export class RectangleF {
constructor(left, top, width, height) {
this._propertyChanged = new EventWithSenderArg();
this._left = typeof left == "number" ? left : 0;
this._top = typeof top == "number" ? top : 0;
this._width = (typeof width == "number") ? width : 2;
this._height = (typeof height == "number") ? height : 2;
this._id = Math.random().toString();
}
toJSON() {
return { left: this.left, top: this.top, width: this.width, height: this.height, id: this._id };
}
get left() {
return this._left;
}
set left(value) {
if (EqualsOfFloatNumbers(value, this._left, RectangleF._tolerance))
return;
this._left = value;
this._propertyChanged.notify(this, "left");
}
get top() {
return this._top;
}
set top(value) {
if (EqualsOfFloatNumbers(value, this._top, RectangleF._tolerance))
return;
this._top = value;
this._propertyChanged.notify(this, "top");
}
get width() {
return this._width;
}
set width(value) {
if (EqualsOfFloatNumbers(value, this._width, RectangleF._tolerance))
return;
this._width = value;
this._propertyChanged.notify(this, "width");
}
get height() {
return this._height;
}
set height(value) {
if (EqualsOfFloatNumbers(value, this._height, RectangleF._tolerance))
return;
this._height = value;
this._propertyChanged.notify(this, "height");
}
get id() {
return this._id;
}
static FromLTRB(left, top, right, bottom) {
var width = Math.abs(right - left);
var height = Math.abs(bottom - top);
return new RectangleF(Math.min(left, right), Math.min(top, bottom), width, height);
}
static fromLtrbObject(obj) {
return RectangleF.FromLTRB(obj.left, obj.top, obj.right, obj.bottom);
}
static FromObject(object) {
return new RectangleF(object.left, object.top, object.width, object.height);
}
/**
* Creates a rectangle that represents the intersetion between a and b.
* If there is no intersection, empty rectangle is returned.
*/
static intersect(a, b) {
var maxLeft = Math.max(a.left, b.left);
var minRight = Math.min(a.right, b.right);
var maxTop = Math.max(a.top, b.top);
var minBottom = Math.min(a.bottom, b.bottom);
if (minRight >= maxLeft && minBottom >= maxTop)
return new RectangleF(maxLeft, maxTop, minRight - maxLeft, minBottom - maxTop);
return RectangleF.empty;
}
;
static union(a, b) {
var x1 = Math.min(a.left, b.left);
var x2 = Math.max(a.left + a.width, b.left + b.width);
var y1 = Math.min(a.top, b.top);
var y2 = Math.max(a.top + a.height, b.top + b.height);
return new RectangleF(x1, y1, x2 - x1, y2 - y1);
}
;
static get empty() {
return new RectangleF(0, 0, -1, -1);
}
equals(other) {
return RectangleF.isEqual(this, other);
}
static isEqual(a, b, tolerance = 0.0001) {
if (a == null && b == null)
return true;
if (a == null || b == null)
return false;
return EqualsOfFloatNumbers(a.left, b.left, tolerance) &&
EqualsOfFloatNumbers(a.top, b.top, tolerance) &&
EqualsOfFloatNumbers(a.width, b.width, tolerance) &&
EqualsOfFloatNumbers(a.height, b.height, tolerance);
}
contains(point, includeBorder, tolerance) {
if (includeBorder == null)
includeBorder = false;
if (includeBorder) {
if (typeof tolerance != "number")
tolerance = 0.0001;
var left = this.left, top = this.top, right = this.left + this.width, bottom = this.top + this.height;
return (point.x > left || EqualsOfFloatNumbers(point.x, left, tolerance)) &&
(point.y > top || EqualsOfFloatNumbers(point.y, top, tolerance)) &&
(point.x < right || EqualsOfFloatNumbers(point.x, right, tolerance)) &&
(point.y < bottom || EqualsOfFloatNumbers(point.y, bottom, tolerance));
}
else {
return point.x > this.left &&
point.y > this.top &&
point.x < this.left + this.width &&
point.y < this.top + this.height;
}
}
containsRectangle(rectangle) {
var leftTop = new PointF(rectangle.left, rectangle.top);
var rightBottom = new PointF(rectangle.right, rectangle.bottom);
return this.contains(leftTop, true) && this.contains(rightBottom, true);
}
clone() {
return new RectangleF(this.left, this.top, this.width, this.height);
}
isEmpty() {
return (this.width <= 0) || (this.height <= 0);
}
inflate(size) {
this.left -= size;
this.top -= size;
this.width += size * 2;
this.height += size * 2;
}
/**
* Determines if this rectangle intersects with rect
*/
intersectsWith(rect) {
return (rect.left < this.right) &&
(this.left < rect.right) &&
(rect.top < this.bottom) &&
(this.top < rect.bottom);
}
updateByMatrix(matrix) {
const deltaAngle = Math.abs(matrix.angle % 90);
if (!EqualsOfFloatNumbers(deltaAngle, 0) && !EqualsOfFloatNumbers(deltaAngle, 90))
throw new ArgumentException(`RectangleF cannot be transformed by angle (${matrix.angle}!`);
const oldLeftTopPoint = new PointF(this.left, this.top);
const oldRightBottomPoint = new PointF(this.right, this.bottom);
const newLeftTopPoint = matrix.transformPoint(oldLeftTopPoint);
const newRightBottomPoint = matrix.transformPoint(oldRightBottomPoint);
const oldRect = this.clone();
this._left = newLeftTopPoint.x;
this._top = newLeftTopPoint.y;
this._width = newRightBottomPoint.x - this._left;
this._height = newRightBottomPoint.y - this._top;
if (!oldRect.equals(this))
this._propertyChanged.notify(this);
return this;
}
getExpanded(margin) {
return RectangleF.FromLTRB(this.left - margin.left, this.top - margin.top, this.right + margin.right, this.bottom + margin.bottom);
}
toString() {
var r = [this.left, this.top, this.width, this.height];
return r.join(",");
}
static fromString(str) {
var parts = str.replace(", ", ",").split(",");
return new RectangleF(parseFloat(parts[0]), parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3]));
}
static fromPoints(point1, point2) {
return RectangleF.FromLTRB(Math.min(point1.x, point2.x), Math.min(point1.y, point2.y), Math.max(point1.x, point2.x), Math.max(point1.y, point2.y));
}
static getMatrix(initialRect, targetRect) {
const result = new Matrix();
const initialRectCenter = initialRect.center;
const targetRectCenter = targetRect.center;
result.scaleRelativeToPoint(targetRect.width / initialRect.width, targetRect.height / initialRect.height, initialRectCenter);
result.translate((targetRectCenter.x - initialRectCenter.x) / result.scaleX, (targetRectCenter.y - initialRectCenter.y) / result.scaleY);
return result;
}
static getOverallBounds(rects) {
if (rects == null || rects.length === 0)
return RectangleF.empty;
return rects.reduce((result, value) => {
if (result == null)
return result = value.clone();
return RectangleF.union(result, value);
});
}
set right(value) {
this.width = value - this.left;
}
get right() {
return this.left + this.width;
}
set bottom(value) {
this.height = value - this.top;
}
get bottom() {
return this.top + this.height;
}
get center() {
return new PointF(this.left + this.width / 2, this.top + this.height / 2);
}
addPropertyChanged(listener) {
this._propertyChanged.add(listener);
}
removePropertyChanged(listener) {
this._propertyChanged.remove(listener);
}
}
RectangleF._tolerance = 0.000001;
//# sourceMappingURL=RectangleF.js.map