{"version":3,"file":"ObjectGeometry.min.mjs","names":[],"sources":["../../../../src/shapes/Object/ObjectGeometry.ts"],"sourcesContent":["import type {\n  TBBox,\n  TCornerPoint,\n  TDegree,\n  TMat2D,\n  TOriginX,\n  TOriginY,\n} from '../../typedefs';\nimport { SCALE_X, SCALE_Y, iMatrix } from '../../constants';\nimport { Intersection } from '../../Intersection';\nimport { Point } from '../../Point';\nimport { makeBoundingBoxFromPoints } from '../../util/misc/boundingBoxFromPoints';\nimport {\n  createRotateMatrix,\n  createTranslateMatrix,\n  composeMatrix,\n  invertTransform,\n  multiplyTransformMatrices,\n  transformPoint,\n  calcPlaneRotation,\n} from '../../util/misc/matrix';\nimport { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';\nimport type { Canvas } from '../../canvas/Canvas';\nimport type { StaticCanvas } from '../../canvas/StaticCanvas';\nimport type { ObjectEvents } from '../../EventTypeDefs';\nimport type { ControlProps } from './types/ControlProps';\nimport { resolveOrigin } from '../../util/misc/resolveOrigin';\nimport type { Group } from '../Group';\nimport { calcDimensionsMatrix } from '../../util/misc/matrix';\nimport { sizeAfterTransform } from '../../util/misc/objectTransforms';\nimport { degreesToRadians } from '../../util/misc/radiansDegreesConversion';\nimport { CommonMethods } from '../../CommonMethods';\nimport type { BaseProps } from './types/BaseProps';\nimport type { FillStrokeProps } from './types/FillStrokeProps';\nimport { CENTER, LEFT, TOP } from '../../constants';\n\ntype TMatrixCache = {\n  key: number[];\n  value: TMat2D;\n};\n\ntype TACoords = TCornerPoint;\n\nexport class ObjectGeometry<EventSpec extends ObjectEvents = ObjectEvents>\n  extends CommonMethods<EventSpec>\n  implements\n    Pick<ControlProps, 'padding'>,\n    BaseProps,\n    Pick<FillStrokeProps, 'strokeWidth' | 'strokeUniform'>\n{\n  // #region Geometry\n\n  declare padding: number;\n\n  /**\n   * Describe object's corner position in scene coordinates.\n   * The coordinates are derived from the following:\n   * left, top, width, height, scaleX, scaleY, skewX, skewY, angle, strokeWidth.\n   * The coordinates do not depend on viewport changes.\n   * The coordinates get updated with {@link setCoords}.\n   * You can calculate them without updating with {@link calcACoords()}\n   */\n  declare aCoords: TACoords;\n\n  /**\n   * storage cache for object transform matrix\n   */\n  declare ownMatrixCache?: TMatrixCache;\n\n  /**\n   * storage cache for object full transform matrix\n   */\n  declare matrixCache?: TMatrixCache;\n\n  /**\n   * A Reference of the Canvas where the object is actually added\n   * @type StaticCanvas | Canvas;\n   * @default undefined\n   * @private\n   */\n  declare canvas?: StaticCanvas | Canvas;\n\n  /**\n   * @returns {number} x position according to object's originX property in canvas coordinate plane\n   */\n  getX(): number {\n    return this.getXY().x;\n  }\n\n  /**\n   * @param {number} value x position according to object's originX property in canvas coordinate plane\n   */\n  setX(value: number) {\n    this.setXY(this.getXY().setX(value));\n  }\n\n  /**\n   * @returns {number} y position according to object's originY property in canvas coordinate plane\n   */\n  getY(): number {\n    return this.getXY().y;\n  }\n\n  /**\n   * @param {number} value y position according to object's originY property in canvas coordinate plane\n   */\n  setY(value: number) {\n    this.setXY(this.getXY().setY(value));\n  }\n\n  /**\n   * @returns {number} x position according to object's originX property in parent's coordinate plane\\\n   * if parent is canvas then this property is identical to {@link getX}\n   */\n  getRelativeX(): number {\n    return this.left;\n  }\n\n  /**\n   * @param {number} value x position according to object's originX property in parent's coordinate plane\\\n   * if parent is canvas then this method is identical to {@link setX}\n   */\n  setRelativeX(value: number) {\n    this.left = value;\n  }\n\n  /**\n   * @returns {number} y position according to object's originY property in parent's coordinate plane\\\n   * if parent is canvas then this property is identical to {@link getY}\n   */\n  getRelativeY(): number {\n    return this.top;\n  }\n\n  /**\n   * @param {number} value y position according to object's originY property in parent's coordinate plane\\\n   * if parent is canvas then this property is identical to {@link setY}\n   */\n  setRelativeY(value: number) {\n    this.top = value;\n  }\n\n  /**\n   * @returns {Point} x position according to object's originX originY properties in canvas coordinate plane\n   */\n  getXY(): Point {\n    const relativePosition = this.getRelativeXY();\n    return this.group\n      ? transformPoint(relativePosition, this.group.calcTransformMatrix())\n      : relativePosition;\n  }\n\n  /**\n   * Set an object position to a particular point, the point is intended in absolute ( canvas ) coordinate.\n   * You can specify originX and originY values,\n   * that otherwise are the object's current values.\n   * @example <caption>Set object's bottom left corner to point (5,5) on canvas</caption>\n   * object.setXY(new Point(5, 5), 'left', 'bottom').\n   * @param {Point} point position in scene coordinate plane\n   * @param {TOriginX} [originX] Horizontal origin: 'left', 'center' or 'right'\n   * @param {TOriginY} [originY] Vertical origin: 'top', 'center' or 'bottom'\n   */\n  setXY(point: Point, originX?: TOriginX, originY?: TOriginY) {\n    if (this.group) {\n      point = transformPoint(\n        point,\n        invertTransform(this.group.calcTransformMatrix()),\n      );\n    }\n    this.setRelativeXY(point, originX, originY);\n  }\n\n  /**\n   * @returns {Point} x,y position according to object's originX originY properties in parent's coordinate plane\n   */\n  getRelativeXY(): Point {\n    return new Point(this.left, this.top);\n  }\n\n  /**\n   * As {@link setXY}, but in current parent's coordinate plane (the current group if any or the canvas)\n   * @param {Point} point position according to object's originX originY properties in parent's coordinate plane\n   * @param {TOriginX} [originX] Horizontal origin: 'left', 'center' or 'right'\n   * @param {TOriginY} [originY] Vertical origin: 'top', 'center' or 'bottom'\n   */\n  setRelativeXY(\n    point: Point,\n    originX: TOriginX = this.originX,\n    originY: TOriginY = this.originY,\n  ) {\n    this.setPositionByOrigin(point, originX, originY);\n  }\n\n  /**\n   * @deprecated intermidiate method to be removed, do not use\n   */\n  protected isStrokeAccountedForInDimensions() {\n    return false;\n  }\n\n  /**\n   * @return {Point[]} [tl, tr, br, bl] in the scene plane\n   */\n  getCoords(): Point[] {\n    const { tl, tr, br, bl } =\n      this.aCoords || (this.aCoords = this.calcACoords());\n    const coords = [tl, tr, br, bl];\n    if (this.group) {\n      const t = this.group.calcTransformMatrix();\n      return coords.map((p) => transformPoint(p, t));\n    }\n    return coords;\n  }\n\n  /**\n   * Checks if object intersects with the scene rect formed by tl and br\n   */\n  intersectsWithRect(tl: Point, br: Point): boolean {\n    const intersection = Intersection.intersectPolygonRectangle(\n      this.getCoords(),\n      tl,\n      br,\n    );\n    return intersection.status === 'Intersection';\n  }\n\n  /**\n   * Checks if object intersects with another object\n   * @param {Object} other Object to test\n   * @return {Boolean} true if object intersects with another object\n   */\n  intersectsWithObject(other: ObjectGeometry): boolean {\n    const intersection = Intersection.intersectPolygonPolygon(\n      this.getCoords(),\n      other.getCoords(),\n    );\n\n    return (\n      intersection.status === 'Intersection' ||\n      intersection.status === 'Coincident' ||\n      other.isContainedWithinObject(this) ||\n      this.isContainedWithinObject(other)\n    );\n  }\n\n  /**\n   * Checks if object is fully contained within area of another object\n   * @param {Object} other Object to test\n   * @return {Boolean} true if object is fully contained within area of another object\n   */\n  isContainedWithinObject(other: ObjectGeometry): boolean {\n    const points = this.getCoords();\n    return points.every((point) => other.containsPoint(point));\n  }\n\n  /**\n   * Checks if object is fully contained within the scene rect formed by tl and br\n   */\n  isContainedWithinRect(tl: Point, br: Point): boolean {\n    const { left, top, width, height } = this.getBoundingRect();\n    return (\n      left >= tl.x &&\n      left + width <= br.x &&\n      top >= tl.y &&\n      top + height <= br.y\n    );\n  }\n\n  isOverlapping<T extends ObjectGeometry>(other: T): boolean {\n    return (\n      this.intersectsWithObject(other) ||\n      this.isContainedWithinObject(other) ||\n      other.isContainedWithinObject(this)\n    );\n  }\n\n  /**\n   * Checks if point is inside the object\n   * @param {Point} point Point to check against\n   * @return {Boolean} true if point is inside the object\n   */\n  containsPoint(point: Point): boolean {\n    return Intersection.isPointInPolygon(point, this.getCoords());\n  }\n\n  /**\n   * Checks if object is contained within the canvas with current viewportTransform\n   * the check is done stopping at first point that appears on screen\n   * @return {Boolean} true if object is fully or partially contained within canvas\n   */\n  isOnScreen(): boolean {\n    if (!this.canvas) {\n      return false;\n    }\n    const { tl, br } = this.canvas.vptCoords;\n    const points = this.getCoords();\n    // if some point is on screen, the object is on screen.\n    if (\n      points.some(\n        (point) =>\n          point.x <= br.x &&\n          point.x >= tl.x &&\n          point.y <= br.y &&\n          point.y >= tl.y,\n      )\n    ) {\n      return true;\n    }\n    // no points on screen, check intersection with absolute coordinates\n    if (this.intersectsWithRect(tl, br)) {\n      return true;\n    }\n    // check if the object is so big that it contains the entire viewport\n    return this.containsPoint(tl.midPointFrom(br));\n  }\n\n  /**\n   * Checks if object is partially contained within the canvas with current viewportTransform\n   * @return {Boolean} true if object is partially contained within canvas\n   */\n  isPartiallyOnScreen(): boolean {\n    if (!this.canvas) {\n      return false;\n    }\n    const { tl, br } = this.canvas.vptCoords;\n    if (this.intersectsWithRect(tl, br)) {\n      return true;\n    }\n    const allPointsAreOutside = this.getCoords().every(\n      (point) =>\n        (point.x >= br.x || point.x <= tl.x) &&\n        (point.y >= br.y || point.y <= tl.y),\n    );\n    // check if the object is so big that it contains the entire viewport\n    return allPointsAreOutside && this.containsPoint(tl.midPointFrom(br));\n  }\n\n  /**\n   * Returns coordinates of object's bounding rectangle (left, top, width, height)\n   * the box is intended as aligned to axis of canvas.\n   * @return {Object} Object with left, top, width, height properties\n   */\n  getBoundingRect(): TBBox {\n    return makeBoundingBoxFromPoints(this.getCoords());\n  }\n\n  /**\n   * Returns width of an object's bounding box counting transformations\n   * @todo shouldn't this account for group transform and return the actual size in canvas coordinate plane?\n   * @return {Number} width value\n   */\n  getScaledWidth(): number {\n    return this._getTransformedDimensions().x;\n  }\n\n  /**\n   * Returns height of an object bounding box counting transformations\n   * @todo shouldn't this account for group transform and return the actual size in canvas coordinate plane?\n   * @return {Number} height value\n   */\n  getScaledHeight(): number {\n    return this._getTransformedDimensions().y;\n  }\n\n  /**\n   * Scales an object (equally by x and y)\n   * @param {Number} value Scale factor\n   * @return {void}\n   */\n  scale(value: number): void {\n    this._set(SCALE_X, value);\n    this._set(SCALE_Y, value);\n    this.setCoords();\n  }\n\n  /**\n   * Scales an object to a given width, with respect to bounding box (scaling by x/y equally)\n   * @param {Number} value New width value\n   * @return {void}\n   */\n  scaleToWidth(value: number) {\n    // adjust to bounding rect factor so that rotated shapes would fit as well\n    const boundingRectFactor =\n      this.getBoundingRect().width / this.getScaledWidth();\n    return this.scale(value / this.width / boundingRectFactor);\n  }\n\n  /**\n   * Scales an object to a given height, with respect to bounding box (scaling by x/y equally)\n   * @param {Number} value New height value\n   * @return {void}\n   */\n  scaleToHeight(value: number) {\n    // adjust to bounding rect factor so that rotated shapes would fit as well\n    const boundingRectFactor =\n      this.getBoundingRect().height / this.getScaledHeight();\n    return this.scale(value / this.height / boundingRectFactor);\n  }\n\n  getCanvasRetinaScaling() {\n    return this.canvas?.getRetinaScaling() || 1;\n  }\n\n  /**\n   * Returns the object angle relative to canvas counting also the group property\n   * @returns {TDegree}\n   */\n  getTotalAngle(): TDegree {\n    return this.group\n      ? radiansToDegrees(calcPlaneRotation(this.calcTransformMatrix()))\n      : this.angle;\n  }\n\n  /**\n   * Retrieves viewportTransform from Object's canvas if available\n   * @return {TMat2D}\n   */\n  getViewportTransform(): TMat2D {\n    return this.canvas?.viewportTransform || (iMatrix.concat() as TMat2D);\n  }\n\n  /**\n   * Calculates the coordinates of the 4 corner of the bbox, in absolute coordinates.\n   * those never change with zoom or viewport changes.\n   * @return {TCornerPoint}\n   */\n  calcACoords(): TCornerPoint {\n    const rotateMatrix = createRotateMatrix({ angle: this.angle }),\n      { x, y } = this.getRelativeCenterPoint(),\n      tMatrix = createTranslateMatrix(x, y),\n      finalMatrix = multiplyTransformMatrices(tMatrix, rotateMatrix),\n      dim = this._getTransformedDimensions(),\n      w = dim.x / 2,\n      h = dim.y / 2;\n    return {\n      // corners\n      tl: transformPoint({ x: -w, y: -h }, finalMatrix),\n      tr: transformPoint({ x: w, y: -h }, finalMatrix),\n      bl: transformPoint({ x: -w, y: h }, finalMatrix),\n      br: transformPoint({ x: w, y: h }, finalMatrix),\n    };\n  }\n\n  /**\n   * Sets corner and controls position coordinates based on current angle, width and height, left and top.\n   * aCoords are used to quickly find an object on the canvas.\n   * See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabric5.fabricjs.com/fabric-gotchas}\n   */\n  setCoords(): void {\n    this.aCoords = this.calcACoords();\n  }\n\n  transformMatrixKey(skipGroup = false): number[] {\n    let prefix: number[] = [];\n    if (!skipGroup && this.group) {\n      prefix = this.group.transformMatrixKey(skipGroup);\n    }\n    prefix.push(\n      this.top,\n      this.left,\n      this.width,\n      this.height,\n      this.scaleX,\n      this.scaleY,\n      this.angle,\n      this.strokeWidth,\n      this.skewX,\n      this.skewY,\n      +this.flipX,\n      +this.flipY,\n      resolveOrigin(this.originX),\n      resolveOrigin(this.originY),\n    );\n\n    return prefix;\n  }\n\n  /**\n   * calculate transform matrix that represents the current transformations from the\n   * object's properties.\n   * @param {Boolean} [skipGroup] return transform matrix for object not counting parent transformations\n   * There are some situation in which this is useful to avoid the fake rotation.\n   * @return {TMat2D} transform matrix for the object\n   */\n  calcTransformMatrix(skipGroup = false): TMat2D {\n    let matrix = this.calcOwnMatrix();\n    if (skipGroup || !this.group) {\n      return matrix;\n    }\n    const key = this.transformMatrixKey(skipGroup),\n      cache = this.matrixCache;\n    if (cache && cache.key.every((x, i) => x === key[i])) {\n      return cache.value;\n    }\n    if (this.group) {\n      matrix = multiplyTransformMatrices(\n        this.group.calcTransformMatrix(false),\n        matrix,\n      );\n    }\n    this.matrixCache = {\n      key,\n      value: matrix,\n    };\n    return matrix;\n  }\n\n  /**\n   * calculate transform matrix that represents the current transformations from the\n   * object's properties, this matrix does not include the group transformation\n   * @return {TMat2D} transform matrix for the object\n   */\n  calcOwnMatrix(): TMat2D {\n    const key = this.transformMatrixKey(true),\n      cache = this.ownMatrixCache;\n    if (cache && cache.key.every((x, i) => x === key[i])) {\n      return cache.value;\n    }\n    const center = this.getRelativeCenterPoint(),\n      options = {\n        angle: this.angle,\n        translateX: center.x,\n        translateY: center.y,\n        scaleX: this.scaleX,\n        scaleY: this.scaleY,\n        skewX: this.skewX,\n        skewY: this.skewY,\n        flipX: this.flipX,\n        flipY: this.flipY,\n      },\n      value = composeMatrix(options);\n    this.ownMatrixCache = {\n      key,\n      value,\n    };\n    return value;\n  }\n\n  /**\n   * Calculate object dimensions from its properties\n   * @private\n   * @returns {Point} dimensions\n   */\n  _getNonTransformedDimensions(): Point {\n    return new Point(this.width, this.height).scalarAdd(this.strokeWidth);\n  }\n\n  /**\n   * Calculate object dimensions for controls box, including padding and canvas zoom.\n   * and active selection\n   * @private\n   * @param {object} [options] transform options\n   * @returns {Point} dimensions\n   */\n  _calculateCurrentDimensions(options?: any): Point {\n    return this._getTransformedDimensions(options)\n      .transform(this.getViewportTransform(), true)\n      .scalarAdd(2 * this.padding);\n  }\n\n  // #region Origin\n\n  declare top: number;\n  declare left: number;\n  declare width: number;\n  declare height: number;\n  declare flipX: boolean;\n  declare flipY: boolean;\n  declare scaleX: number;\n  declare scaleY: number;\n  declare skewX: number;\n  declare skewY: number;\n  /**\n   * @deprecated please use 'center' as value in new projects\n   * */\n  declare originX: TOriginX;\n  /**\n   * @deprecated please use 'center' as value in new projects\n   * */\n  declare originY: TOriginY;\n  declare angle: TDegree;\n  declare strokeWidth: number;\n  declare strokeUniform: boolean;\n\n  /**\n   * Object containing this object.\n   * can influence its size and position\n   */\n  declare group?: Group;\n\n  /**\n   * Calculate object bounding box dimensions from its properties scale, skew.\n   * This bounding box is aligned with object angle and not with canvas axis or screen.\n   * @param {Object} [options]\n   * @param {Number} [options.scaleX]\n   * @param {Number} [options.scaleY]\n   * @param {Number} [options.skewX]\n   * @param {Number} [options.skewY]\n   * @private\n   * @returns {Point} dimensions\n   */\n  _getTransformedDimensions(options: any = {}): Point {\n    const dimOptions = {\n      // if scaleX or scaleY are negative numbers,\n      // this will return dimensions that are negative.\n      // and this will break assumptions around the codebase\n      scaleX: this.scaleX,\n      scaleY: this.scaleY,\n      skewX: this.skewX,\n      skewY: this.skewY,\n      width: this.width,\n      height: this.height,\n      strokeWidth: this.strokeWidth,\n      // TODO remove this spread. is visible in the performance inspection\n      ...options,\n    };\n    // stroke is applied before/after transformations are applied according to `strokeUniform`\n    const strokeWidth = dimOptions.strokeWidth;\n    let preScalingStrokeValue = strokeWidth,\n      postScalingStrokeValue = 0;\n\n    if (this.strokeUniform) {\n      preScalingStrokeValue = 0;\n      postScalingStrokeValue = strokeWidth;\n    }\n    const dimX = dimOptions.width + preScalingStrokeValue,\n      dimY = dimOptions.height + preScalingStrokeValue,\n      noSkew = dimOptions.skewX === 0 && dimOptions.skewY === 0;\n    let finalDimensions;\n    if (noSkew) {\n      finalDimensions = new Point(\n        dimX * dimOptions.scaleX,\n        dimY * dimOptions.scaleY,\n      );\n    } else {\n      finalDimensions = sizeAfterTransform(\n        dimX,\n        dimY,\n        calcDimensionsMatrix(dimOptions),\n      );\n    }\n\n    return finalDimensions.scalarAdd(postScalingStrokeValue);\n  }\n\n  /**\n   * Translates the coordinates from a set of origin to another (based on the object's dimensions)\n   * @param {Point} point The point which corresponds to the originX and originY params\n   * @param {TOriginX} fromOriginX Horizontal origin: 'left', 'center' or 'right'\n   * @param {TOriginY} fromOriginY Vertical origin: 'top', 'center' or 'bottom'\n   * @param {TOriginX} toOriginX Horizontal origin: 'left', 'center' or 'right'\n   * @param {TOriginY} toOriginY Vertical origin: 'top', 'center' or 'bottom'\n   * @return {Point}\n   */\n  translateToGivenOrigin(\n    point: Point,\n    fromOriginX: TOriginX,\n    fromOriginY: TOriginY,\n    toOriginX: TOriginX,\n    toOriginY: TOriginY,\n  ): Point {\n    let x = point.x,\n      y = point.y;\n    const offsetX = resolveOrigin(toOriginX) - resolveOrigin(fromOriginX),\n      offsetY = resolveOrigin(toOriginY) - resolveOrigin(fromOriginY);\n\n    if (offsetX || offsetY) {\n      const dim = this._getTransformedDimensions();\n      x += offsetX * dim.x;\n      y += offsetY * dim.y;\n    }\n\n    return new Point(x, y);\n  }\n\n  /**\n   * Translates the coordinates from origin to center coordinates (based on the object's dimensions)\n   * @param {Point} point The point which corresponds to the originX and originY params\n   * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n   * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n   * @return {Point}\n   */\n  translateToCenterPoint(\n    point: Point,\n    originX: TOriginX,\n    originY: TOriginY,\n  ): Point {\n    if (originX === CENTER && originY === CENTER) {\n      return point;\n    }\n    const p = this.translateToGivenOrigin(\n      point,\n      originX,\n      originY,\n      CENTER,\n      CENTER,\n    );\n    if (this.angle) {\n      return p.rotate(degreesToRadians(this.angle), point);\n    }\n    return p;\n  }\n\n  /**\n   * Translates the coordinates from center to origin coordinates (based on the object's dimensions)\n   * @param {Point} center The point which corresponds to center of the object\n   * @param {OriginX} originX Horizontal origin: 'left', 'center' or 'right'\n   * @param {OriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n   * @return {Point}\n   */\n  translateToOriginPoint(\n    center: Point,\n    originX: TOriginX,\n    originY: TOriginY,\n  ): Point {\n    const p = this.translateToGivenOrigin(\n      center,\n      CENTER,\n      CENTER,\n      originX,\n      originY,\n    );\n    if (this.angle) {\n      return p.rotate(degreesToRadians(this.angle), center);\n    }\n    return p;\n  }\n\n  /**\n   * Returns the center coordinates of the object relative to canvas\n   * @return {Point}\n   */\n  getCenterPoint(): Point {\n    const relCenter = this.getRelativeCenterPoint();\n    return this.group\n      ? transformPoint(relCenter, this.group.calcTransformMatrix())\n      : relCenter;\n  }\n\n  /**\n   * Returns the center coordinates of the object relative to it's parent\n   * @return {Point}\n   */\n  getRelativeCenterPoint(): Point {\n    return this.translateToCenterPoint(\n      new Point(this.left, this.top),\n      this.originX,\n      this.originY,\n    );\n  }\n\n  /**\n   * Alias of {@link getPositionByOrigin}\n   * @deprecated use {@link getPositionByOrigin} instead\n   */\n  getPointByOrigin(originX: TOriginX, originY: TOriginY): Point {\n    return this.getPositionByOrigin(originX, originY);\n  }\n\n  /**\n   * This function is the mirror of {@link setPositionByOrigin}\n   * Returns the position of the object based on specified origin.\n   * Take an object that has left, top set to 100, 100 with origin 'left', 'top'.\n   * Return the values of left top ( wrapped in a point ) that you would need to keep\n   * the same position if origin where different ( ex: center, bottom )\n   * Alternatively you can use this to also find which point in the parent plane is a specific origin\n   * ( where is the bottom right corner of my object? )\n   * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n   * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n   * @return {Point}\n   */\n  getPositionByOrigin(originX: TOriginX, originY: TOriginY) {\n    return this.translateToOriginPoint(\n      this.getRelativeCenterPoint(),\n      originX,\n      originY,\n    );\n  }\n\n  /**\n   * Sets the position of the object taking into consideration the object's origin\n   * @param {Point} pos The new position of the object\n   * @param {TOriginX} originX Horizontal origin: 'left', 'center' or 'right'\n   * @param {TOriginY} originY Vertical origin: 'top', 'center' or 'bottom'\n   * @return {void}\n   */\n  setPositionByOrigin(pos: Point, originX: TOriginX, originY: TOriginY) {\n    const center = this.translateToCenterPoint(pos, originX, originY),\n      position = this.translateToOriginPoint(\n        center,\n        this.originX,\n        this.originY,\n      );\n    this.set({ left: position.x, top: position.y });\n  }\n\n  /**\n   * @private\n   */\n  _getLeftTopCoords() {\n    return this.getPositionByOrigin(LEFT, TOP);\n  }\n\n  /**\n   * An utility method to position the object by its left top corner.\n   * Useful to reposition objects since now the default origin is center/center\n   * Places the left/top corner of the object bounding box in p.\n   */\n  positionByLeftTop(p: Point) {\n    return this.setPositionByOrigin(p, LEFT, TOP);\n  }\n}\n"],"mappings":"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"}