From d4bcf4ebd51479c1b4342babd10ec83c5c519eaf Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Thu, 4 Aug 2022 17:05:26 +0300 Subject: [PATCH 01/22] Update point.class.ts --- src/point.class.ts | 678 +++++++++++++++++++++++---------------------- 1 file changed, 340 insertions(+), 338 deletions(-) diff --git a/src/point.class.ts b/src/point.class.ts index ecd11d4516d..def736ce41a 100644 --- a/src/point.class.ts +++ b/src/point.class.ts @@ -1,344 +1,346 @@ -//@ts-nocheck -(function(global) { - /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ - var fabric = global.fabric || (global.fabric = { }); +interface IPoint { + x: number + y: number +} - fabric.Point = Point; +/** + * Adaptation of work of Kevin Lindsey(kevin@kevlindev.com) + */ +export class Point { + + x: number + + y: number + + type = 'point' + + static toPoint(from: IPoint) { + return new Point(from.x, from.y); + } + + constructor(x = 0, y = 0) { + this.x = x; + this.y = y; + } + + /** + * Adds another point to this one and returns another one + * @param {Point} that + * @return {Point} new Point instance with added values + */ + add(that: Point): Point { + return new Point(this.x + that.x, this.y + that.y); + } + + /** + * Adds another point to this one + * @param {Point} that + * @return {Point} thisArg + * @chainable + */ + addEquals(that: Point): Point { + this.x += that.x; + this.y += that.y; + return this; + } + + /** + * Adds value to this point and returns a new one + * @param {Number} scalar + * @return {Point} new Point with added value + */ + scalarAdd(scalar: number): Point { + return new Point(this.x + scalar, this.y + scalar); + } + + /** + * Adds value to this point + * @param {Number} scalar + * @return {Point} thisArg + * @chainable + */ + scalarAddEquals(scalar: number): Point { + this.x += scalar; + this.y += scalar; + return this; + } + + /** + * Subtracts another point from this point and returns a new one + * @param {IPoint} that + * @return {Point} new Point object with subtracted values + */ + subtract(that: IPoint): Point { + return new Point(this.x - that.x, this.y - that.y); + } + + /** + * Subtracts another point from this point + * @param {Point} that + * @return {Point} thisArg + * @chainable + */ + subtractEquals(that: Point): Point { + this.x -= that.x; + this.y -= that.y; + return this; + } + + /** + * Subtracts value from this point and returns a new one + * @param {Number} scalar + * @return {Point} + */ + scalarSubtract(scalar: number): Point { + return new Point(this.x - scalar, this.y - scalar); + } /** - * Point class - * @class fabric.Point - * @memberOf fabric - * @constructor + * Subtracts value from this point + * @param {Number} scalar + * @return {Point} thisArg + * @chainable + */ + scalarSubtractEquals(scalar: number): Point { + this.x -= scalar; + this.y -= scalar; + return this; + } + + /** + * Multiplies this point by another value and returns a new one + * @param {Point} that + * @return {Point} + */ + multiply(that: Point): Point { + return new Point(this.x * that.x, this.y * that.y); + } + + /** + * Multiplies this point by a value and returns a new one + * @param {Number} scalar + * @return {Point} + */ + scalarMultiply(scalar: number): Point { + return new Point(this.x * scalar, this.y * scalar); + } + + /** + * Multiplies this point by a value + * @param {Number} scalar + * @return {Point} thisArg + * @chainable + */ + scalarMultiplyEquals(scalar: number): Point { + this.x *= scalar; + this.y *= scalar; + return this; + } + + /** + * Divides this point by another and returns a new one + * @param {Point} that + * @return {Point} + */ + divide(that: Point): Point { + return new Point(this.x / that.x, this.y / that.y); + } + + /** + * Divides this point by a value and returns a new one + * @param {Number} scalar + * @return {Point} + */ + scalarDivide(scalar: number): Point { + return new Point(this.x / scalar, this.y / scalar); + } + + /** + * Divides this point by a value + * @param {Number} scalar + * @return {Point} thisArg + * @chainable + */ + scalarDivideEquals(scalar: number): Point { + this.x /= scalar; + this.y /= scalar; + return this; + } + + /** + * Returns true if this point is equal to another one + * @param {Point} that + * @return {Boolean} + */ + eq(that: Point): boolean { + return (this.x === that.x && this.y === that.y); + } + + /** + * Returns true if this point is less than another one + * @param {Point} that + * @return {Boolean} + */ + lt(that: Point): boolean { + return (this.x < that.x && this.y < that.y); + } + + /** + * Returns true if this point is less than or equal to another one + * @param {Point} that + * @return {Boolean} + */ + lte(that: Point): boolean { + return (this.x <= that.x && this.y <= that.y); + } + + /** + + * Returns true if this point is greater another one + * @param {Point} that + * @return {Boolean} + */ + gt(that: Point): boolean { + return (this.x > that.x && this.y > that.y); + } + + /** + * Returns true if this point is greater than or equal to another one + * @param {Point} that + * @return {Boolean} + */ + gte(that: Point): boolean { + return (this.x >= that.x && this.y >= that.y); + } + + /** + * Returns new point which is the result of linear interpolation with this one and another one + * @param {Point} that + * @param {Number} t , position of interpolation, between 0 and 1 default 0.5 + * @return {Point} + */ + lerp(that: Point, t = 0.5): Point { + t = Math.max(Math.min(1, t), 0); + return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); + } + + /** + * Returns distance from this point and another one + * @param {Point} that + * @return {Number} + */ + distanceFrom(that: Point): number { + const dx = this.x - that.x, + dy = this.y - that.y; + return Math.sqrt(dx * dx + dy * dy); + } + + /** + * Returns the point between this point and another one + * @param {Point} that + * @return {Point} + */ + midPointFrom(that: Point): Point { + return this.lerp(that); + } + + /** + * Returns a new point which is the min of this and another one + * @param {Point} that + * @return {Point} + */ + min(that: Point): Point { + return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); + } + + /** + * Returns a new point which is the max of this and another one + * @param {Point} that + * @return {Point} + */ + max(that: Point): Point { + return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); + } + + /** + * Returns string representation of this point + * @return {String} + */ + toString(): string { + return this.x + ',' + this.y; + } + + /** + * Sets x/y of this point * @param {Number} x * @param {Number} y - * @return {fabric.Point} thisArg - */ - function Point(x, y) { - this.x = x || 0; - this.y = y || 0; - } - - Point.prototype = /** @lends fabric.Point.prototype */ { - - type: 'point', - - constructor: Point, - - /** - * Adds another point to this one and returns another one - * @param {fabric.Point} that - * @return {fabric.Point} new Point instance with added values - */ - add: function (that) { - return new Point(this.x + that.x, this.y + that.y); - }, - - /** - * Adds another point to this one - * @param {fabric.Point} that - * @return {fabric.Point} thisArg - * @chainable - */ - addEquals: function (that) { - this.x += that.x; - this.y += that.y; - return this; - }, - - /** - * Adds value to this point and returns a new one - * @param {Number} scalar - * @return {fabric.Point} new Point with added value - */ - scalarAdd: function (scalar) { - return new Point(this.x + scalar, this.y + scalar); - }, - - /** - * Adds value to this point - * @param {Number} scalar - * @return {fabric.Point} thisArg - * @chainable - */ - scalarAddEquals: function (scalar) { - this.x += scalar; - this.y += scalar; - return this; - }, - - /** - * Subtracts another point from this point and returns a new one - * @param {fabric.Point} that - * @return {fabric.Point} new Point object with subtracted values - */ - subtract: function (that) { - return new Point(this.x - that.x, this.y - that.y); - }, - - /** - * Subtracts another point from this point - * @param {fabric.Point} that - * @return {fabric.Point} thisArg - * @chainable - */ - subtractEquals: function (that) { - this.x -= that.x; - this.y -= that.y; - return this; - }, - - /** - * Subtracts value from this point and returns a new one - * @param {Number} scalar - * @return {fabric.Point} - */ - scalarSubtract: function (scalar) { - return new Point(this.x - scalar, this.y - scalar); - }, - - /** - * Subtracts value from this point - * @param {Number} scalar - * @return {fabric.Point} thisArg - * @chainable - */ - scalarSubtractEquals: function (scalar) { - this.x -= scalar; - this.y -= scalar; - return this; - }, - - /** - * Multiplies this point by another value and returns a new one - * @param {fabric.Point} that - * @return {fabric.Point} - */ - multiply: function (that) { - return new Point(this.x * that.x, this.y * that.y); - }, - - /** - * Multiplies this point by a value and returns a new one - * @param {Number} scalar - * @return {fabric.Point} - */ - scalarMultiply: function (scalar) { - return new Point(this.x * scalar, this.y * scalar); - }, - - /** - * Multiplies this point by a value - * @param {Number} scalar - * @return {fabric.Point} thisArg - * @chainable - */ - scalarMultiplyEquals: function (scalar) { - this.x *= scalar; - this.y *= scalar; - return this; - }, - - /** - * Divides this point by another and returns a new one - * @param {fabric.Point} that - * @return {fabric.Point} - */ - divide: function (that) { - return new Point(this.x / that.x, this.y / that.y); - }, - - /** - * Divides this point by a value and returns a new one - * @param {Number} scalar - * @return {fabric.Point} - */ - scalarDivide: function (scalar) { - return new Point(this.x / scalar, this.y / scalar); - }, - - /** - * Divides this point by a value - * @param {Number} scalar - * @return {fabric.Point} thisArg - * @chainable - */ - scalarDivideEquals: function (scalar) { - this.x /= scalar; - this.y /= scalar; - return this; - }, - - /** - * Returns true if this point is equal to another one - * @param {fabric.Point} that - * @return {Boolean} - */ - eq: function (that) { - return (this.x === that.x && this.y === that.y); - }, - - /** - * Returns true if this point is less than another one - * @param {fabric.Point} that - * @return {Boolean} - */ - lt: function (that) { - return (this.x < that.x && this.y < that.y); - }, - - /** - * Returns true if this point is less than or equal to another one - * @param {fabric.Point} that - * @return {Boolean} - */ - lte: function (that) { - return (this.x <= that.x && this.y <= that.y); - }, - - /** - - * Returns true if this point is greater another one - * @param {fabric.Point} that - * @return {Boolean} - */ - gt: function (that) { - return (this.x > that.x && this.y > that.y); - }, - - /** - * Returns true if this point is greater than or equal to another one - * @param {fabric.Point} that - * @return {Boolean} - */ - gte: function (that) { - return (this.x >= that.x && this.y >= that.y); - }, - - /** - * Returns new point which is the result of linear interpolation with this one and another one - * @param {fabric.Point} that - * @param {Number} t , position of interpolation, between 0 and 1 default 0.5 - * @return {fabric.Point} - */ - lerp: function (that, t) { - if (typeof t === 'undefined') { - t = 0.5; - } - t = Math.max(Math.min(1, t), 0); - return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t); - }, - - /** - * Returns distance from this point and another one - * @param {fabric.Point} that - * @return {Number} - */ - distanceFrom: function (that) { - var dx = this.x - that.x, - dy = this.y - that.y; - return Math.sqrt(dx * dx + dy * dy); - }, - - /** - * Returns the point between this point and another one - * @param {fabric.Point} that - * @return {fabric.Point} - */ - midPointFrom: function (that) { - return this.lerp(that); - }, - - /** - * Returns a new point which is the min of this and another one - * @param {fabric.Point} that - * @return {fabric.Point} - */ - min: function (that) { - return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y)); - }, - - /** - * Returns a new point which is the max of this and another one - * @param {fabric.Point} that - * @return {fabric.Point} - */ - max: function (that) { - return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y)); - }, - - /** - * Returns string representation of this point - * @return {String} - */ - toString: function () { - return this.x + ',' + this.y; - }, - - /** - * Sets x/y of this point - * @param {Number} x - * @param {Number} y - * @chainable - */ - setXY: function (x, y) { - this.x = x; - this.y = y; - return this; - }, - - /** - * Sets x of this point - * @param {Number} x - * @chainable - */ - setX: function (x) { - this.x = x; - return this; - }, - - /** - * Sets y of this point - * @param {Number} y - * @chainable - */ - setY: function (y) { - this.y = y; - return this; - }, - - /** - * Sets x/y of this point from another point - * @param {fabric.Point} that - * @chainable - */ - setFromPoint: function (that) { - this.x = that.x; - this.y = that.y; - return this; - }, - - /** - * Swaps x/y of this point and another point - * @param {fabric.Point} that - */ - swap: function (that) { - var x = this.x, - y = this.y; - this.x = that.x; - this.y = that.y; - that.x = x; - that.y = y; - }, - - /** - * return a cloned instance of the point - * @return {fabric.Point} - */ - clone: function () { - return new Point(this.x, this.y); - } - }; - -})(typeof exports !== 'undefined' ? exports : window); + * @chainable + */ + setXY(x: number, y: number) { + this.x = x; + this.y = y; + return this; + } + + /** + * Sets x of this point + * @param {Number} x + * @chainable + */ + setX(x: number) { + this.x = x; + return this; + } + + /** + * Sets y of this point + * @param {Number} y + * @chainable + */ + setY(y: number) { + this.y = y; + return this; + } + + /** + * Sets x/y of this point from another point + * @param {Point} that + * @chainable + */ + setFromPoint(that: Point) { + this.x = that.x; + this.y = that.y; + return this; + } + + /** + * Swaps x/y of this point and another point + * @param {Point} that + */ + swap(that: Point) { + const x = this.x, + y = this.y; + this.x = that.x; + this.y = that.y; + that.x = x; + that.y = y; + } + + /** + * + * @returns absolute point + */ + abs() { + return new Point(Math.abs(this.x), Math.abs(this.y)); + } + + /** + * return a cloned instance of the point + * @return {Point} + */ + clone(): Point { + return new Point(this.x, this.y); + } +} + From 5a198040b7c38585bccb85c2e3fcc1a65ffd64f7 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Thu, 4 Aug 2022 17:24:37 +0300 Subject: [PATCH 02/22] import point --- src/brushes/circle_brush.class.ts | 6 ++- src/brushes/pencil_brush.class.ts | 12 ++--- src/brushes/spray_brush.class.ts | 4 +- src/canvas.class.ts | 14 +++--- src/controls.actions.ts | 4 +- src/intersection.class.ts | 26 ++++++----- src/mixins/canvas_grouping.mixin.ts | 6 ++- src/mixins/eraser_brush.mixin.ts | 4 +- src/mixins/itext_behavior.mixin.ts | 8 ++-- src/mixins/object_geometry.mixin.ts | 34 +++++++------- src/mixins/object_interactivity.mixin.ts | 10 +++-- src/mixins/object_origin.mixin.ts | 50 +++++++++++---------- src/point.class.ts | 6 ++- src/shapes/group.class.ts | 32 +++++++------- src/shapes/object.class.ts | 14 +++--- src/static_canvas.class.ts | 32 +++++++------- src/util/animate.ts | 4 +- src/util/dom_event.ts | 4 +- src/util/misc.ts | 56 ++++++++++++------------ src/util/path.ts | 16 ++++--- 20 files changed, 191 insertions(+), 151 deletions(-) diff --git a/src/brushes/circle_brush.class.ts b/src/brushes/circle_brush.class.ts index b7ac11c8883..0efc18ea5ef 100644 --- a/src/brushes/circle_brush.class.ts +++ b/src/brushes/circle_brush.class.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + import { Color } from "../color"; @@ -128,10 +130,10 @@ import { Color } from "../color"; /** * @param {Object} pointer - * @return {fabric.Point} Just added pointer point + * @return {Point} Just added pointer point */ addPoint: function(pointer) { - var pointerPoint = new fabric.Point(pointer.x, pointer.y), + var pointerPoint = new Point(pointer.x, pointer.y), circleRadius = fabric.util.getRandomInt( Math.max(0, this.width - 20), this.width + 20) / 2, diff --git a/src/brushes/pencil_brush.class.ts b/src/brushes/pencil_brush.class.ts index 59ae1b7070b..c1ffd02cfbe 100644 --- a/src/brushes/pencil_brush.class.ts +++ b/src/brushes/pencil_brush.class.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { var fabric = global.fabric; /** @@ -124,7 +126,7 @@ */ _prepareForDrawing: function(pointer) { - var p = new fabric.Point(pointer.x, pointer.y); + var p = new Point(pointer.x, pointer.y); this._reset(); this._addPoint(p); @@ -133,7 +135,7 @@ /** * @private - * @param {fabric.Point} point Point to be added to points array + * @param {Point} point Point to be added to points array */ _addPoint: function(point) { if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) { @@ -163,7 +165,7 @@ * @param {Object} pointer Actual mouse position related to the canvas. */ _captureDrawingPath: function(pointer) { - var pointerPoint = new fabric.Point(pointer.x, pointer.y); + var pointerPoint = new Point(pointer.x, pointer.y); return this._addPoint(pointerPoint); }, @@ -185,8 +187,8 @@ //that's why we set them apart a bit if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) { var width = this.width / 1000; - p1 = new fabric.Point(p1.x, p1.y); - p2 = new fabric.Point(p2.x, p2.y); + p1 = new Point(p1.x, p1.y); + p2 = new Point(p2.x, p2.y); p1.x -= width; p2.x += width; } diff --git a/src/brushes/spray_brush.class.ts b/src/brushes/spray_brush.class.ts index 430c4ca84d6..236434e8010 100644 --- a/src/brushes/spray_brush.class.ts +++ b/src/brushes/spray_brush.class.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { var fabric = global.fabric; /** @@ -212,7 +214,7 @@ width = this.dotWidth; } - var point = new fabric.Point(x, y); + var point = new Point(x, y); point.width = width; if (this.randomOpacity) { diff --git a/src/canvas.class.ts b/src/canvas.class.ts index 06f800e0cbb..5ad7f28a555 100644 --- a/src/canvas.class.ts +++ b/src/canvas.class.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from './point.class'; + (function(global) { var fabric = global.fabric, getPointer = fabric.util.getPointer, @@ -790,9 +792,9 @@ */ _drawSelection: function (ctx) { var selector = this._groupSelector, - viewportStart = new fabric.Point(selector.ex, selector.ey), + viewportStart = new Point(selector.ex, selector.ey), start = fabric.util.transformPoint(viewportStart, this.viewportTransform), - viewportExtent = new fabric.Point(selector.ex + selector.left, selector.ey + selector.top), + viewportExtent = new Point(selector.ex + selector.left, selector.ey + selector.top), extent = fabric.util.transformPoint(viewportExtent, this.viewportTransform), minX = Math.min(start.x, extent.x), minY = Math.min(start.y, extent.y), @@ -970,7 +972,7 @@ * of the time. * @param {Event} e * @param {Boolean} ignoreVpt - * @return {fabric.Point} + * @return {Point} */ getPointer: function (e, ignoreVpt) { // return cached values if we are in the event processing chain @@ -1012,10 +1014,10 @@ // If bounds are not available (i.e. not visible), do not apply scale. cssScale = boundsWidth === 0 || boundsHeight === 0 ? - new fabric.Point(1, 1) : - new fabric.Point(upperCanvasEl.width / boundsWidth, upperCanvasEl.height / boundsHeight); + new Point(1, 1) : + new Point(upperCanvasEl.width / boundsWidth, upperCanvasEl.height / boundsHeight); - return new fabric.Point( + return new Point( pointer.x * cssScale.x, pointer.y * cssScale.y ); diff --git a/src/controls.actions.ts b/src/controls.actions.ts index eef182d37e2..8ae5c5eea4a 100644 --- a/src/controls.actions.ts +++ b/src/controls.actions.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from './point.class'; + (function(global) { var fabric = global.fabric || (global.fabric = { }), scaleMap = ['e', 'se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'], @@ -229,7 +231,7 @@ control = target.controls[transform.corner], zoom = target.canvas.getZoom(), padding = target.padding / zoom, - localPoint = target.normalizePoint(new fabric.Point(x, y), originX, originY); + localPoint = target.normalizePoint(new Point(x, y), originX, originY); if (localPoint.x >= padding) { localPoint.x -= padding; } diff --git a/src/intersection.class.ts b/src/intersection.class.ts index d7f5edafef6..e8fed9d635d 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from './point.class'; + (function(global) { /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ var fabric = global.fabric || (global.fabric = { }); @@ -21,7 +23,7 @@ /** * Appends a point to intersection - * @param {fabric.Point} point + * @param {Point} point * @return {fabric.Intersection} thisArg * @chainable */ @@ -46,10 +48,10 @@ * Checks if one line intersects another * TODO: rename in intersectSegmentSegment * @static - * @param {fabric.Point} a1 - * @param {fabric.Point} a2 - * @param {fabric.Point} b1 - * @param {fabric.Point} b2 + * @param {Point} a1 + * @param {Point} a2 + * @param {Point} b1 + * @param {Point} b2 * @return {fabric.Intersection} */ fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) { @@ -62,7 +64,7 @@ ub = ubT / uB; if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { result = new Intersection('Intersection'); - result.appendPoint(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); + result.appendPoint(new Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); } else { result = new Intersection(); @@ -84,8 +86,8 @@ * TODO: rename in intersectSegmentPolygon * fix detection of coincident * @static - * @param {fabric.Point} a1 - * @param {fabric.Point} a2 + * @param {Point} a1 + * @param {Point} a2 * @param {Array} points * @return {fabric.Intersection} */ @@ -135,15 +137,15 @@ * Checks if polygon intersects rectangle * @static * @param {Array} points - * @param {fabric.Point} r1 - * @param {fabric.Point} r2 + * @param {Point} r1 + * @param {Point} r2 * @return {fabric.Intersection} */ fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) { var min = r1.min(r2), max = r1.max(r2), - topRight = new fabric.Point(max.x, min.y), - bottomLeft = new fabric.Point(min.x, max.y), + topRight = new Point(max.x, min.y), + bottomLeft = new Point(min.x, max.y), inter1 = Intersection.intersectLinePolygon(min, topRight, points), inter2 = Intersection.intersectLinePolygon(topRight, max, points), inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), diff --git a/src/mixins/canvas_grouping.mixin.ts b/src/mixins/canvas_grouping.mixin.ts index 48bd9aaef1c..4ffb9fd2a85 100644 --- a/src/mixins/canvas_grouping.mixin.ts +++ b/src/mixins/canvas_grouping.mixin.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { var fabric = global.fabric, @@ -142,8 +144,8 @@ y1 = this._groupSelector.ey, x2 = x1 + this._groupSelector.left, y2 = y1 + this._groupSelector.top, - selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)), - selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)), + selectionX1Y1 = new Point(min(x1, x2), min(y1, y2)), + selectionX2Y2 = new Point(max(x1, x2), max(y1, y2)), allowIntersect = !this.selectionFullyContained, isClick = x1 === x2 && y1 === y2; // we iterate reverse order to collect top first in case of click. diff --git a/src/mixins/eraser_brush.mixin.ts b/src/mixins/eraser_brush.mixin.ts index 8f3cef1c1f8..db4d54bc25e 100644 --- a/src/mixins/eraser_brush.mixin.ts +++ b/src/mixins/eraser_brush.mixin.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function (global) { /** ERASER_START */ @@ -509,7 +511,7 @@ /** * - * @param {fabric.Point} pointer + * @param {Point} pointer * @param {fabric.IEvent} options * @returns */ diff --git a/src/mixins/itext_behavior.mixin.ts b/src/mixins/itext_behavior.mixin.ts index f24ab951fcc..db6dc26ae98 100644 --- a/src/mixins/itext_behavior.mixin.ts +++ b/src/mixins/itext_behavior.mixin.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { var fabric = global.fabric; fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.prototype */ { @@ -433,9 +435,9 @@ */ setDragImage: function (e, data) { var t = this.calcTransformMatrix(); - var flipFactor = new fabric.Point(this.flipX ? -1 : 1, this.flipY ? -1 : 1); + var flipFactor = new Point(this.flipX ? -1 : 1, this.flipY ? -1 : 1); var boundaries = this._getCursorBoundaries(data.selectionStart); - var selectionPosition = new fabric.Point( + var selectionPosition = new Point( boundaries.left + boundaries.leftOffset, boundaries.top + boundaries.topOffset ).multiply(flipFactor); @@ -445,7 +447,7 @@ var enableRetinaScaling = this.canvas._isRetinaScaling(); var retinaScaling = this.canvas.getRetinaScaling(); var bbox = this.getBoundingRect(true); - var correction = pos.subtract(new fabric.Point(bbox.left, bbox.top)); + var correction = pos.subtract(new Point(bbox.left, bbox.top)); var offset = correction.add(diff).scalarMultiply(retinaScaling); // prepare instance for drag image snapshot by making all non selected text invisible var bgc = this.backgroundColor; diff --git a/src/mixins/object_geometry.mixin.ts b/src/mixins/object_geometry.mixin.ts index 5636a720389..ef586e57eca 100644 --- a/src/mixins/object_geometry.mixin.ts +++ b/src/mixins/object_geometry.mixin.ts @@ -1,12 +1,14 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { function arrayFromCoords(coords) { return [ - new fabric.Point(coords.tl.x, coords.tl.y), - new fabric.Point(coords.tr.x, coords.tr.y), - new fabric.Point(coords.br.x, coords.br.y), - new fabric.Point(coords.bl.x, coords.bl.y) + new Point(coords.tl.x, coords.tl.y), + new Point(coords.tr.x, coords.tr.y), + new Point(coords.br.x, coords.br.y), + new Point(coords.bl.x, coords.bl.y) ]; } @@ -142,8 +144,8 @@ * You can specify {@link fabric.Object#originX} and {@link fabric.Object#originY} values, * that otherwise are the object's current values. * @example Set object's bottom left corner to point (5,5) on canvas - * object.setXY(new fabric.Point(5, 5), 'left', 'bottom'). - * @param {fabric.Point} point position in canvas coordinate plane + * object.setXY(new Point(5, 5), 'left', 'bottom'). + * @param {Point} point position in canvas coordinate plane * @param {'left'|'center'|'right'|number} [originX] Horizontal origin: 'left', 'center' or 'right' * @param {'top'|'center'|'bottom'|number} [originY] Vertical origin: 'top', 'center' or 'bottom' */ @@ -161,12 +163,12 @@ * @returns {number} x position according to object's {@link fabric.Object#originX} {@link fabric.Object#originY} properties in parent's coordinate plane */ getRelativeXY: function () { - return new fabric.Point(this.left, this.top); + return new Point(this.left, this.top); }, /** * As {@link fabric.Object#setXY}, but in current parent's coordinate plane ( the current group if any or the canvas) - * @param {fabric.Point} point position according to object's {@link fabric.Object#originX} {@link fabric.Object#originY} properties in parent's coordinate plane + * @param {Point} point position according to object's {@link fabric.Object#originX} {@link fabric.Object#originY} properties in parent's coordinate plane * @param {'left'|'center'|'right'|number} [originX] Horizontal origin: 'left', 'center' or 'right' * @param {'top'|'center'|'bottom'|number} [originY] Vertical origin: 'top', 'center' or 'bottom' */ @@ -283,7 +285,7 @@ /** * Checks if point is inside the object - * @param {fabric.Point} point Point to check against + * @param {Point} point Point to check against * @param {Object} [lines] object returned from @method _getImageLines * @param {Boolean} [absolute] use coordinates without viewportTransform * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords @@ -409,7 +411,7 @@ * Helper method to determine how many cross points are between the 4 object edges * and the horizontal line determined by a point on canvas * @private - * @param {fabric.Point} point Point to check + * @param {Point} point Point to check * @param {Object} lines Coordinates of the object being evaluated */ // remove yi, not used but left code here just in case. @@ -708,10 +710,10 @@ /** * Calculate object dimensions from its properties * @private - * @returns {fabric.Point} dimensions + * @returns {Point} dimensions */ _getNonTransformedDimensions: function() { - return new fabric.Point(this.width, this.height).scalarAddEquals(this.strokeWidth); + return new Point(this.width, this.height).scalarAddEquals(this.strokeWidth); }, /** @@ -722,7 +724,7 @@ * @param {Number} [options.skewX] * @param {Number} [options.skewY] * @private - * @returns {fabric.Point} dimensions + * @returns {Point} dimensions */ _getTransformedDimensions: function (options) { options = Object.assign({ @@ -749,11 +751,11 @@ finalDimensions, noSkew = options.skewX === 0 && options.skewY === 0; if (noSkew) { - finalDimensions = new fabric.Point(dimX * options.scaleX, dimY * options.scaleY); + finalDimensions = new Point(dimX * options.scaleX, dimY * options.scaleY); } else { var bbox = util.sizeAfterTransform(dimX, dimY, options); - finalDimensions = new fabric.Point(bbox.x, bbox.y); + finalDimensions = new Point(bbox.x, bbox.y); } return finalDimensions.scalarAddEquals(postScalingStrokeValue); @@ -764,7 +766,7 @@ * and active selection * @private * @param {object} [options] transform options - * @returns {fabric.Point} dimensions + * @returns {Point} dimensions */ _calculateCurrentDimensions: function(options) { var vpt = this.getViewportTransform(), diff --git a/src/mixins/object_interactivity.mixin.ts b/src/mixins/object_interactivity.mixin.ts index 81241e4231d..52a56190c90 100644 --- a/src/mixins/object_interactivity.mixin.ts +++ b/src/mixins/object_interactivity.mixin.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { var fabric = global.fabric, degreesToRadians = fabric.util.degreesToRadians; @@ -111,7 +113,7 @@ /** * @public override this function in order to customize the drawing of the control box, e.g. rounded corners, different border style. * @param {CanvasRenderingContext2D} ctx ctx is rotated and translated so that (0,0) is at object's center - * @param {fabric.Point} size the control box size used + * @param {Point} size the control box size used */ strokeBorders: function (ctx, size) { ctx.strokeRect( @@ -125,7 +127,7 @@ /** * @private * @param {CanvasRenderingContext2D} ctx Context to draw on - * @param {fabric.Point} size + * @param {Point} size * @param {Object} styleOverride object to override the object style */ _drawBorders: function (ctx, size, styleOverride) { @@ -157,8 +159,8 @@ if ((styleOverride && styleOverride.forActiveSelection) || this.group) { var bbox = fabric.util.sizeAfterTransform(this.width, this.height, options), strokeFactor = this.strokeUniform ? - new fabric.Point(0, 0).scalarAddEquals(this.canvas.getZoom()) : - new fabric.Point(options.scaleX, options.scaleY), + new Point(0, 0).scalarAddEquals(this.canvas.getZoom()) : + new Point(options.scaleX, options.scaleY), stroke = strokeFactor.scalarMultiplyEquals(this.strokeWidth); size = bbox.addEquals(stroke).scalarAddEquals(this.borderScaleFactor); } diff --git a/src/mixins/object_origin.mixin.ts b/src/mixins/object_origin.mixin.ts index b716bbb11de..b94acee827d 100644 --- a/src/mixins/object_origin.mixin.ts +++ b/src/mixins/object_origin.mixin.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { var fabric = global.fabric, degreesToRadians = fabric.util.degreesToRadians, @@ -46,12 +48,12 @@ /** * Translates the coordinates from a set of origin to another (based on the object's dimensions) - * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @param {Point} point The point which corresponds to the originX and originY params * @param {OriginX} fromOriginX Horizontal origin: 'left', 'center' or 'right' * @param {OriginY} fromOriginY Vertical origin: 'top', 'center' or 'bottom' * @param {OriginX} toOriginX Horizontal origin: 'left', 'center' or 'right' * @param {OriginY} toOriginY Vertical origin: 'top', 'center' or 'bottom' - * @return {fabric.Point} + * @return {Point} */ translateToGivenOrigin: function(point, fromOriginX, fromOriginY, toOriginX, toOriginY) { var x = point.x, @@ -66,15 +68,15 @@ y = point.y + offsetY * dim.y; } - return new fabric.Point(x, y); + return new Point(x, y); }, /** * Translates the coordinates from origin to center coordinates (based on the object's dimensions) - * @param {fabric.Point} point The point which corresponds to the originX and originY params + * @param {Point} point The point which corresponds to the originX and originY params * @param {OriginX} originX Horizontal origin: 'left', 'center' or 'right' * @param {OriginY} originY Vertical origin: 'top', 'center' or 'bottom' - * @return {fabric.Point} + * @return {Point} */ translateToCenterPoint: function(point, originX, originY) { var p = this.translateToGivenOrigin(point, originX, originY, 'center', 'center'); @@ -86,10 +88,10 @@ /** * Translates the coordinates from center to origin coordinates (based on the object's dimensions) - * @param {fabric.Point} center The point which corresponds to center of the object + * @param {Point} center The point which corresponds to center of the object * @param {OriginX} originX Horizontal origin: 'left', 'center' or 'right' * @param {OriginY} originY Vertical origin: 'top', 'center' or 'bottom' - * @return {fabric.Point} + * @return {Point} */ translateToOriginPoint: function(center, originX, originY) { var p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY); @@ -101,7 +103,7 @@ /** * Returns the center coordinates of the object relative to canvas - * @return {fabric.Point} + * @return {Point} */ getCenterPoint: function() { var relCenter = this.getRelativeCenterPoint(); @@ -112,7 +114,7 @@ /** * Returns the center coordinates of the object relative to it's containing group or null - * @return {fabric.Point|null} point or null of object has no parent group + * @return {Point|null} point or null of object has no parent group */ getCenterPointRelativeToParent: function () { return this.group ? this.getRelativeCenterPoint() : null; @@ -120,16 +122,16 @@ /** * Returns the center coordinates of the object relative to it's parent - * @return {fabric.Point} + * @return {Point} */ getRelativeCenterPoint: function () { - return this.translateToCenterPoint(new fabric.Point(this.left, this.top), this.originX, this.originY); + return this.translateToCenterPoint(new Point(this.left, this.top), this.originX, this.originY); }, /** * Returns the coordinates of the object based on center coordinates - * @param {fabric.Point} point The point which corresponds to the originX and originY params - * @return {fabric.Point} + * @param {Point} point The point which corresponds to the originX and originY params + * @return {Point} */ // getOriginPoint: function(center) { // return this.translateToOriginPoint(center, this.originX, this.originY); @@ -139,7 +141,7 @@ * Returns the coordinates of the object as if it has a different origin * @param {OriginX} originX Horizontal origin: 'left', 'center' or 'right' * @param {OriginY} originY Vertical origin: 'top', 'center' or 'bottom' - * @return {fabric.Point} + * @return {Point} */ getPointByOrigin: function(originX, originY) { var center = this.getRelativeCenterPoint(); @@ -148,10 +150,10 @@ /** * Returns the normalized point (rotated relative to center) in local coordinates - * @param {fabric.Point} point The point relative to instance coordinate system + * @param {Point} point The point relative to instance coordinate system * @param {OriginX} originX Horizontal origin: 'left', 'center' or 'right' * @param {OriginY} originY Vertical origin: 'top', 'center' or 'bottom' - * @return {fabric.Point} + * @return {Point} */ normalizePoint: function(point, originX, originY) { var center = this.getRelativeCenterPoint(), p, p2; @@ -159,10 +161,10 @@ p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY); } else { - p = new fabric.Point(this.left, this.top); + p = new Point(this.left, this.top); } - p2 = new fabric.Point(point.x, point.y); + p2 = new Point(point.x, point.y); if (this.angle) { p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle)); } @@ -178,23 +180,23 @@ getLocalPointer: function (e, pointer) { pointer = pointer || this.canvas.getPointer(e); return fabric.util.transformPoint( - new fabric.Point(pointer.x, pointer.y), + new Point(pointer.x, pointer.y), fabric.util.invertTransform(this.calcTransformMatrix()) - ).addEquals(new fabric.Point(this.width / 2, this.height / 2)); + ).addEquals(new Point(this.width / 2, this.height / 2)); }, /** * Returns the point in global coordinates - * @param {fabric.Point} The point relative to the local coordinate system - * @return {fabric.Point} + * @param {Point} The point relative to the local coordinate system + * @return {Point} */ // toGlobalPoint: function(point) { - // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new fabric.Point(this.left, this.top)); + // return fabric.util.rotatePoint(point, this.getCenterPoint(), degreesToRadians(this.angle)).addEquals(new Point(this.left, this.top)); // }, /** * Sets the position of the object taking into consideration the object's origin - * @param {fabric.Point} pos The new position of the object + * @param {Point} pos The new position of the object * @param {OriginX} originX Horizontal origin: 'left', 'center' or 'right' * @param {OriginY} originY Vertical origin: 'top', 'center' or 'bottom' * @return {void} diff --git a/src/point.class.ts b/src/point.class.ts index def736ce41a..1920c6b6f28 100644 --- a/src/point.class.ts +++ b/src/point.class.ts @@ -1,3 +1,4 @@ +import { fabric } from '../HEADER'; interface IPoint { x: number @@ -68,10 +69,10 @@ export class Point { /** * Subtracts another point from this point and returns a new one - * @param {IPoint} that + * @param {Point} that * @return {Point} new Point object with subtracted values */ - subtract(that: IPoint): Point { + subtract(that: Point): Point { return new Point(this.x - that.x, this.y - that.y); } @@ -344,3 +345,4 @@ export class Point { } } +fabric.Point = Point; \ No newline at end of file diff --git a/src/shapes/group.class.ts b/src/shapes/group.class.ts index fc75da8d458..7883e9450fc 100644 --- a/src/shapes/group.class.ts +++ b/src/shapes/group.class.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function (global) { var fabric = global.fabric || (global.fabric = {}), multiplyTransformMatrices = fabric.util.multiplyTransformMatrices, @@ -482,7 +484,7 @@ /** * @private * @param {fabric.Object} object - * @param {fabric.Point} diff + * @param {Point} diff */ _adjustObjectPosition: function (object, diff) { object.set({ @@ -515,8 +517,8 @@ var result = this.getLayoutStrategyResult(this.layout, this._objects.concat(), context); if (result) { // handle positioning - var newCenter = new fabric.Point(result.centerX, result.centerY); - var vector = center.subtract(newCenter).add(new fabric.Point(result.correctionX || 0, result.correctionY || 0)); + var newCenter = new Point(result.centerX, result.centerY); + var vector = center.subtract(newCenter).add(new Point(result.correctionX || 0, result.correctionY || 0)); var diff = transformPoint(vector, invertTransform(this.calcOwnMatrix()), true); // set dimensions this.set({ width: result.width, height: result.height }); @@ -632,7 +634,7 @@ clipPathCenter = transformPoint(clipPathRelativeCenter, this.calcOwnMatrix(), true); if (context.type === 'initialization' || context.type === 'layout_change') { var bbox = this.prepareBoundingBox(layoutDirective, objects, context) || {}; - center = new fabric.Point(bbox.centerX || 0, bbox.centerY || 0); + center = new Point(bbox.centerX || 0, bbox.centerY || 0); return { centerX: center.x + clipPathCenter.x, centerY: center.y + clipPathCenter.y, @@ -711,9 +713,9 @@ var bbox = this.getObjectsBoundingBox(objects) || {}; var width = hasWidth ? this.width : (bbox.width || 0), height = hasHeight ? this.height : (bbox.height || 0), - calculatedCenter = new fabric.Point(bbox.centerX || 0, bbox.centerY || 0), - origin = new fabric.Point(this.resolveOriginX(this.originX), this.resolveOriginY(this.originY)), - size = new fabric.Point(width, height), + calculatedCenter = new Point(bbox.centerX || 0, bbox.centerY || 0), + origin = new Point(this.resolveOriginX(this.originX), this.resolveOriginY(this.originY)), + size = new Point(width, height), strokeWidthVector = this._getTransformedDimensions({ width: 0, height: 0 }), sizeAfter = this._getTransformedDimensions({ width: width, @@ -725,20 +727,20 @@ height: bbox.height, strokeWidth: 0 }), - rotationCorrection = new fabric.Point(0, 0); + rotationCorrection = new Point(0, 0); // calculate center and correction var originT = origin.scalarAdd(0.5); var originCorrection = sizeAfter.multiply(originT); - var centerCorrection = new fabric.Point( + var centerCorrection = new Point( hasWidth ? bboxSizeAfter.x / 2 : originCorrection.x, hasHeight ? bboxSizeAfter.y / 2 : originCorrection.y ); - var center = new fabric.Point( + var center = new Point( hasX ? this.left - (sizeAfter.x + strokeWidthVector.x) * origin.x : calculatedCenter.x - centerCorrection.x, hasY ? this.top - (sizeAfter.y + strokeWidthVector.y) * origin.y : calculatedCenter.y - centerCorrection.y ); - var offsetCorrection = new fabric.Point( + var offsetCorrection = new Point( hasX ? center.x - calculatedCenter.x + bboxSizeAfter.x * (hasWidth ? 0.5 : 0) : -(hasWidth ? (sizeAfter.x - strokeWidthVector.x) * 0.5 : sizeAfter.x * originT.x), @@ -746,7 +748,7 @@ center.y - calculatedCenter.y + bboxSizeAfter.y * (hasHeight ? 0.5 : 0) : -(hasHeight ? (sizeAfter.y - strokeWidthVector.y) * 0.5 : sizeAfter.y * originT.y) ).add(rotationCorrection); - var correction = new fabric.Point( + var correction = new Point( hasWidth ? -sizeAfter.x / 2 : 0, hasHeight ? -sizeAfter.y / 2 : 0 ).add(offsetCorrection); @@ -781,13 +783,13 @@ cos = Math.abs(fabric.util.cos(rad)), rx = sizeVector.x * cos + sizeVector.y * sin, ry = sizeVector.x * sin + sizeVector.y * cos; - sizeVector = new fabric.Point(rx, ry); + sizeVector = new Point(rx, ry); } a = objCenter.subtract(sizeVector); b = objCenter.add(sizeVector); if (i === 0) { - min = new fabric.Point(Math.min(a.x, b.x), Math.min(a.y, b.y)); - max = new fabric.Point(Math.max(a.x, b.x), Math.max(a.y, b.y)); + min = new Point(Math.min(a.x, b.x), Math.min(a.y, b.y)); + max = new Point(Math.max(a.x, b.x), Math.max(a.y, b.y)); } else { min.setXY(Math.min(min.x, a.x, b.x), Math.min(min.y, a.y, b.y)); diff --git a/src/shapes/object.class.ts b/src/shapes/object.class.ts index 4ffcdf0b10c..5bc12c0cd5a 100644 --- a/src/shapes/object.class.ts +++ b/src/shapes/object.class.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { var fabric = global.fabric || (global.fabric = { }), extend = fabric.util.object.extend, @@ -920,7 +922,7 @@ /** * Return the object scale factor counting also the group scaling - * @return {fabric.Point} + * @return {Point} */ getObjectScaling: function() { // if the object is a top level one, on the canvas, we go for simple aritmetic @@ -928,11 +930,11 @@ // and will likely kill the cache when not needed // https://github.com/fabricjs/fabric.js/issues/7157 if (!this.group) { - return new fabric.Point(Math.abs(this.scaleX), Math.abs(this.scaleY)); + return new Point(Math.abs(this.scaleX), Math.abs(this.scaleY)); } // if we are inside a group total zoom calculation is complex, we defer to generic matrices var options = fabric.util.qrDecompose(this.calcTransformMatrix()); - return new fabric.Point(Math.abs(options.scaleX), Math.abs(options.scaleY)); + return new Point(Math.abs(options.scaleX), Math.abs(options.scaleY)); }, /** @@ -1412,7 +1414,7 @@ var shadow = this.shadow, canvas = this.canvas, multX = (canvas && canvas.viewportTransform[0]) || 1, multY = (canvas && canvas.viewportTransform[3]) || 1, - scaling = shadow.nonScaling ? new fabric.Point(1, 1) : this.getObjectScaling(); + scaling = shadow.nonScaling ? new Point(1, 1) : this.getObjectScaling(); if (canvas && canvas._isRetinaScaling()) { multX *= fabric.devicePixelRatio; multY *= fabric.devicePixelRatio; @@ -1697,7 +1699,7 @@ if (shadow) { var shadowBlur = shadow.blur; - var scaling = shadow.nonScaling ? new fabric.Point(1, 1) : this.getObjectScaling(); + var scaling = shadow.nonScaling ? new Point(1, 1) : this.getObjectScaling(); // consider non scaling shadow. shadowOffset.x = 2 * Math.round(abs(shadow.offsetX) + shadowBlur) * (abs(scaling.x)); shadowOffset.y = 2 * Math.round(abs(shadow.offsetY) + shadowBlur) * (abs(scaling.y)); @@ -1716,7 +1718,7 @@ if (options.format === 'jpeg') { canvas.backgroundColor = '#fff'; } - this.setPositionByOrigin(new fabric.Point(canvas.width / 2, canvas.height / 2), 'center', 'center'); + this.setPositionByOrigin(new Point(canvas.width / 2, canvas.height / 2), 'center', 'center'); var originalCanvas = this.canvas; canvas._objects = [this]; this.set('canvas', canvas); diff --git a/src/static_canvas.class.ts b/src/static_canvas.class.ts index 28ae9d4bb2f..36664ced8a5 100644 --- a/src/static_canvas.class.ts +++ b/src/static_canvas.class.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from './point.class'; + (function (global) { // aliases for faster resolution var fabric = global.fabric, extend = fabric.util.object.extend, @@ -495,7 +497,7 @@ * meaning that following zoom to point with the same point will have the visual * effect of the zoom originating from that point. The point won't move. * It has nothing to do with canvas center or visual center of the viewport. - * @param {fabric.Point} point to zoom with respect to + * @param {Point} point to zoom with respect to * @param {Number} value to set zoom to, less than 1 zooms out * @return {fabric.Canvas} instance * @chainable true @@ -519,13 +521,13 @@ * @chainable true */ setZoom: function (value) { - this.zoomToPoint(new fabric.Point(0, 0), value); + this.zoomToPoint(new Point(0, 0), value); return this; }, /** * Pan viewport so as to place point at top left corner of canvas - * @param {fabric.Point} point to move to + * @param {Point} point to move to * @return {fabric.Canvas} instance * @chainable true */ @@ -538,12 +540,12 @@ /** * Pans viewpoint relatively - * @param {fabric.Point} point (position vector) to move by + * @param {Point} point (position vector) to move by * @return {fabric.Canvas} instance * @chainable true */ relativePan: function (point) { - return this.absolutePan(new fabric.Point( + return this.absolutePan(new Point( -point.x - this.viewportTransform[4], -point.y - this.viewportTransform[5] )); @@ -722,8 +724,8 @@ max = a.max(b); return this.vptCoords = { tl: min, - tr: new fabric.Point(max.x, min.y), - bl: new fabric.Point(min.x, max.y), + tr: new Point(max.x, min.y), + bl: new Point(min.x, max.y), br: max, }; }, @@ -876,10 +878,10 @@ /** * Returns coordinates of a center of canvas. - * @return {fabric.Point} + * @return {Point} */ getCenterPoint: function () { - return new fabric.Point(this.width / 2, this.height / 2); + return new Point(this.width / 2, this.height / 2); }, /** @@ -888,7 +890,7 @@ * @return {fabric.Canvas} thisArg */ centerObjectH: function (object) { - return this._centerObject(object, new fabric.Point(this.getCenterPoint().x, object.getCenterPoint().y)); + return this._centerObject(object, new Point(this.getCenterPoint().x, object.getCenterPoint().y)); }, /** @@ -898,7 +900,7 @@ * @chainable */ centerObjectV: function (object) { - return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenterPoint().y)); + return this._centerObject(object, new Point(object.getCenterPoint().x, this.getCenterPoint().y)); }, /** @@ -931,7 +933,7 @@ */ viewportCenterObjectH: function(object) { var vpCenter = this.getVpCenter(); - this._centerObject(object, new fabric.Point(vpCenter.x, object.getCenterPoint().y)); + this._centerObject(object, new Point(vpCenter.x, object.getCenterPoint().y)); return this; }, @@ -944,12 +946,12 @@ viewportCenterObjectV: function(object) { var vpCenter = this.getVpCenter(); - return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, vpCenter.y)); + return this._centerObject(object, new Point(object.getCenterPoint().x, vpCenter.y)); }, /** * Calculate the point in canvas that correspond to the center of actual viewport. - * @return {fabric.Point} vpCenter, viewport center + * @return {Point} vpCenter, viewport center * @chainable */ getVpCenter: function() { @@ -961,7 +963,7 @@ /** * @private * @param {fabric.Object} object Object to center - * @param {fabric.Point} center Center point + * @param {Point} center Center point * @return {fabric.Canvas} thisArg * @chainable */ diff --git a/src/util/animate.ts b/src/util/animate.ts index 525ed8a13f4..e7bfb699a64 100644 --- a/src/util/animate.ts +++ b/src/util/animate.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function (global) { /** * @@ -128,7 +130,7 @@ * startValue: [1, 2, 3], * endValue: [2, 4, 6], * onChange: function([x, y, zoom]) { - * canvas.zoomToPoint(new fabric.Point(x, y), zoom); + * canvas.zoomToPoint(new Point(x, y), zoom); * canvas.requestRenderAll(); * } * }); diff --git a/src/util/dom_event.ts b/src/util/dom_event.ts index 76404e72c7c..6c53df9da0f 100644 --- a/src/util/dom_event.ts +++ b/src/util/dom_event.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function (global) { // since ie11 can use addEventListener but they do not support options, i need to check var fabric = global.fabric, couldUseAttachEvent = !!fabric.document.createElement('div').attachEvent, @@ -39,7 +41,7 @@ var element = event.target, scroll = fabric.util.getScrollLeftTop(element), _evt = getTouchInfo(event); - return new fabric.Point(_evt.clientX + scroll.left, _evt.clientY + scroll.top); + return new Point(_evt.clientX + scroll.left, _evt.clientY + scroll.top); }; fabric.util.isTouchEvent = function(event) { diff --git a/src/util/misc.ts b/src/util/misc.ts index a0aff79ed67..d336ddab8c9 100644 --- a/src/util/misc.ts +++ b/src/util/misc.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + import { cos } from './cos'; (function(global) { var fabric = global.fabric, sqrt = Math.sqrt, @@ -92,13 +94,13 @@ import { cos } from './cos'; * Rotates `point` around `origin` with `radians` * @static * @memberOf fabric.util - * @param {fabric.Point} point The point to rotate - * @param {fabric.Point} origin The origin of the rotation + * @param {Point} point The point to rotate + * @param {Point} origin The origin of the rotation * @param {Number} radians The radians of the angle for the rotation - * @return {fabric.Point} The new rotated point + * @return {Point} The new rotated point */ rotatePoint: function(point, origin, radians) { - var newPoint = new fabric.Point(point.x - origin.x, point.y - origin.y), + var newPoint = new Point(point.x - origin.x, point.y - origin.y), v = fabric.util.rotateVector(newPoint, radians); return v.addEquals(origin); }, @@ -109,14 +111,14 @@ import { cos } from './cos'; * @memberOf fabric.util * @param {Object} vector The vector to rotate (x and y) * @param {Number} radians The radians of the angle for the rotation - * @return {fabric.Point} The new rotated point + * @return {Point} The new rotated point */ rotateVector: function(vector, radians) { var sin = fabric.util.sin(radians), cos = fabric.util.cos(radians), rx = vector.x * cos - vector.y * sin, ry = vector.x * sin + vector.y * cos; - return new fabric.Point(rx, ry); + return new Point(rx, ry); }, /** @@ -133,7 +135,7 @@ import { cos } from './cos'; * @returns {Point} vector */ createVector: function (from, to) { - return new fabric.Point(to.x - from.x, to.y - from.y); + return new Point(to.x - from.x, to.y - from.y); }, /** @@ -155,7 +157,7 @@ import { cos } from './cos'; * @returns {Point} vector representing the unit vector of pointing to the direction of `v` */ getHatVector: function (v) { - return new fabric.Point(v.x, v.y).scalarMultiply(1 / Math.hypot(v.x, v.y)); + return new Point(v.x, v.y).scalarMultiply(1 / Math.hypot(v.x, v.y)); }, /** @@ -195,19 +197,19 @@ import { cos } from './cos'; * @param {number} options.scaleX * @param {number} options.scaleY * @param {boolean} [openPath] whether the shape is open or not, affects the calculations of the first and last points - * @returns {fabric.Point[]} array of size 2n/4n of all suspected points + * @returns {Point[]} array of size 2n/4n of all suspected points */ projectStrokeOnPoints: function (points, options, openPath) { var coords = [], s = options.strokeWidth / 2, strokeUniformScalar = options.strokeUniform ? - new fabric.Point(1 / options.scaleX, 1 / options.scaleY) : new fabric.Point(1, 1), + new Point(1 / options.scaleX, 1 / options.scaleY) : new Point(1, 1), getStrokeHatVector = function (v) { var scalar = s / (Math.hypot(v.x, v.y)); - return new fabric.Point(v.x * scalar * strokeUniformScalar.x, v.y * scalar * strokeUniformScalar.y); + return new Point(v.x * scalar * strokeUniformScalar.x, v.y * scalar * strokeUniformScalar.y); }; if (points.length <= 1) {return coords;} points.forEach(function (p, index) { - var A = new fabric.Point(p.x, p.y), B, C; + var A = new Point(p.x, p.y), B, C; if (index === 0) { C = points[index + 1]; B = openPath ? getStrokeHatVector(fabric.util.createVector(C, A)).addEquals(A) : points[points.length - 1]; @@ -227,7 +229,7 @@ import { cos } from './cos'; miterVector; if (options.strokeLineJoin === 'miter') { scalar = -s / Math.sin(alpha / 2); - miterVector = new fabric.Point( + miterVector = new Point( bisectorVector.x * scalar * strokeUniformScalar.x, bisectorVector.y * scalar * strokeUniformScalar.y ); @@ -238,7 +240,7 @@ import { cos } from './cos'; } } scalar = -s * Math.SQRT2; - miterVector = new fabric.Point( + miterVector = new Point( bisectorVector.x * scalar * strokeUniformScalar.x, bisectorVector.y * scalar * strokeUniformScalar.y ); @@ -252,19 +254,19 @@ import { cos } from './cos'; * Apply transform t to point p * @static * @memberOf fabric.util - * @param {fabric.Point} p The point to transform + * @param {Point} p The point to transform * @param {Array} t The transform * @param {Boolean} [ignoreOffset] Indicates that the offset should not be applied - * @return {fabric.Point} The transformed point + * @return {Point} The transformed point */ transformPoint: function(p, t, ignoreOffset) { if (ignoreOffset) { - return new fabric.Point( + return new Point( t[0] * p.x + t[2] * p.y, t[1] * p.x + t[3] * p.y ); } - return new fabric.Point( + return new Point( t[0] * p.x + t[2] * p.y + t[4], t[1] * p.x + t[3] * p.y + t[5] ); @@ -277,17 +279,17 @@ import { cos } from './cos'; * @example Send point from canvas plane to group plane * var obj = new fabric.Rect({ left: 20, top: 20, width: 60, height: 60, strokeWidth: 0 }); * var group = new fabric.Group([obj], { strokeWidth: 0 }); - * var sentPoint1 = fabric.util.sendPointToPlane(new fabric.Point(50, 50), null, group.calcTransformMatrix()); - * var sentPoint2 = fabric.util.sendPointToPlane(new fabric.Point(50, 50), fabric.iMatrix, group.calcTransformMatrix()); + * var sentPoint1 = fabric.util.sendPointToPlane(new Point(50, 50), null, group.calcTransformMatrix()); + * var sentPoint2 = fabric.util.sendPointToPlane(new Point(50, 50), fabric.iMatrix, group.calcTransformMatrix()); * console.log(sentPoint1, sentPoint2) // both points print (0,0) which is the center of group * * @static * @memberOf fabric.util * @see {fabric.util.transformPointRelativeToCanvas} for transforming relative to canvas - * @param {fabric.Point} point + * @param {Point} point * @param {Matrix} [from] plane matrix containing object. Passing `null` is equivalent to passing the identity matrix, which means `point` exists in the canvas coordinate plane. * @param {Matrix} [to] destination plane matrix to contain object. Passing `null` means `point` should be sent to the canvas coordinate plane. - * @returns {fabric.Point} transformed point + * @returns {Point} transformed point */ sendPointToPlane: function (point, from, to) { // we are actually looking for the transformation from the destination plane to the source plane (which is a linear mapping) @@ -310,11 +312,11 @@ import { cos } from './cos'; * * @static * @memberOf fabric.util - * @param {fabric.Point} point + * @param {Point} point * @param {fabric.StaticCanvas} canvas * @param {'sibling'|'child'} relationBefore current relation of point to canvas * @param {'sibling'|'child'} relationAfter desired relation of point to canvas - * @returns {fabric.Point} transformed point + * @returns {Point} transformed point */ transformPointRelativeToCanvas: function (point, canvas, relationBefore, relationAfter) { if (relationBefore !== 'child' && relationBefore !== 'sibling') { @@ -1076,7 +1078,7 @@ import { cos } from './cos'; */ applyTransformToObject: function(object, transform) { var options = fabric.util.qrDecompose(transform), - center = new fabric.Point(options.translateX, options.translateY); + center = new Point(options.translateX, options.translateY); object.flipX = false; object.flipY = false; object.set('scaleX', options.scaleX); @@ -1144,7 +1146,7 @@ import { cos } from './cos'; * @param {Number} options.scaleY * @param {Number} options.skewX * @param {Number} options.skewY - * @returns {fabric.Point} size + * @returns {Point} size */ sizeAfterTransform: function(width, height, options) { var dimX = width / 2, dimY = height / 2, @@ -1167,7 +1169,7 @@ import { cos } from './cos'; }], transformMatrix = fabric.util.calcDimensionsMatrix(options), bbox = fabric.util.makeBoundingBoxFromPoints(points, transformMatrix); - return new fabric.Point(bbox.width, bbox.height); + return new Point(bbox.width, bbox.height); }, /** diff --git a/src/util/path.ts b/src/util/path.ts index 3006875baff..b24a69d4188 100644 --- a/src/util/path.ts +++ b/src/util/path.ts @@ -1,4 +1,6 @@ //@ts-nocheck +import { Point } from '../point.class'; + (function(global) { var fabric = global.fabric, _join = Array.prototype.join, @@ -643,15 +645,15 @@ return { x: segInfo.x, y: segInfo.y, angle: 0 }; case 'Z': case 'z': - info = new fabric.Point(segInfo.x, segInfo.y).lerp( - new fabric.Point(segInfo.destX, segInfo.destY), + info = new Point(segInfo.x, segInfo.y).lerp( + new Point(segInfo.destX, segInfo.destY), segPercent ); info.angle = Math.atan2(segInfo.destY - segInfo.y, segInfo.destX - segInfo.x); return info; case 'L': - info = new fabric.Point(segInfo.x, segInfo.y).lerp( - new fabric.Point(segment[1], segment[2]), + info = new Point(segInfo.x, segInfo.y).lerp( + new Point(segment[1], segment[2]), segPercent ); info.angle = Math.atan2(segment[2] - segInfo.y, segment[1] - segInfo.x); @@ -752,8 +754,8 @@ */ function getSmoothPathFromPoints(points, correction) { var path = [], i, - p1 = new fabric.Point(points[0].x, points[0].y), - p2 = new fabric.Point(points[1].x, points[1].y), + p1 = new Point(points[0].x, points[0].y), + p2 = new Point(points[1].x, points[1].y), len = points.length, multSignX = 1, multSignY = 0, manyPoints = len > 2; correction = correction || 0; @@ -830,7 +832,7 @@ var d = []; for (var i = 0, rad, coord; i < numVertexes; i++) { rad = i * interiorAngle + rotationAdjustment; - coord = new fabric.Point(Math.cos(rad), Math.sin(rad)).scalarMultiplyEquals(radius); + coord = new Point(Math.cos(rad), Math.sin(rad)).scalarMultiplyEquals(radius); d.push([i === 0 ? 'M' : 'L', coord.x, coord.y]); } d.push(['Z']); From 20d3e7762ef8bd143d378a2148ced29af97eb2d2 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Thu, 4 Aug 2022 17:46:15 +0300 Subject: [PATCH 03/22] migrate --- src/intersection.class.ts | 150 +++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 77 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index e8fed9d635d..c23ce1deef1 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -1,48 +1,42 @@ //@ts-nocheck -import { Point } from './point.class'; +import { Point } from "./point.class"; +import { fabric } from '../HEADER'; -(function(global) { - /* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ - var fabric = global.fabric || (global.fabric = { }); - /** - * Intersection class - * @class fabric.Intersection - * @memberOf fabric - * @constructor - */ - function Intersection(status) { +/* Adaptation of work of Kevin Lindsey (kevin@kevlindev.com) */ + +type IntersectionType = 'Intersection' | 'Coincident' | 'Parallel'; + +export class Intersection { + + points: Point[] + + constructor(status?: IntersectionType) { this.status = status; this.points = []; } - fabric.Intersection = Intersection; - - fabric.Intersection.prototype = /** @lends fabric.Intersection.prototype */ { - - constructor: Intersection, - - /** - * Appends a point to intersection - * @param {Point} point - * @return {fabric.Intersection} thisArg - * @chainable - */ - appendPoint: function (point) { - this.points.push(point); - return this; - }, - - /** - * Appends points to intersection - * @param {Array} points - * @return {fabric.Intersection} thisArg - * @chainable - */ - appendPoints: function (points) { - this.points = this.points.concat(points); - return this; - } - }; + /** + * Appends a point to intersection + * @param {Point} point + * @return {Intersection} thisArg + * @chainable + */ + appendPoint(point) { + this.points.push(point); + return this; + } + + /** + * Appends points to intersection + * @param {Array} points + * @return {Intersection} thisArg + * @chainable + */ + appendPoints(points) { + this.points = this.points.concat(points); + return this; + } + /** * Checks if one line intersects another @@ -52,16 +46,16 @@ import { Point } from './point.class'; * @param {Point} a2 * @param {Point} b1 * @param {Point} b2 - * @return {fabric.Intersection} + * @return {Intersection} */ - fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) { - var result, - uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), - ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), - uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); + static intersectLineLine(a1, a2, b1, b2) { + let result, + uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), + ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), + uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); if (uB !== 0) { - var ua = uaT / uB, - ub = ubT / uB; + const ua = uaT / uB, + ub = ubT / uB; if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { result = new Intersection('Intersection'); result.appendPoint(new Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); @@ -79,7 +73,7 @@ import { Point } from './point.class'; } } return result; - }; + } /** * Checks if line intersects polygon @@ -89,14 +83,14 @@ import { Point } from './point.class'; * @param {Point} a1 * @param {Point} a2 * @param {Array} points - * @return {fabric.Intersection} + * @return {Intersection} */ - fabric.Intersection.intersectLinePolygon = function(a1, a2, points) { - var result = new Intersection(), - length = points.length, - b1, b2, inter, i; + static intersectLinePolygon(a1, a2, points) { + const result = new Intersection(), + length = points.length; + let b1, b2, inter; - for (i = 0; i < length; i++) { + for (let i = 0; i < length; i++) { b1 = points[i]; b2 = points[(i + 1) % length]; inter = Intersection.intersectLineLine(a1, a2, b1, b2); @@ -107,23 +101,23 @@ import { Point } from './point.class'; result.status = 'Intersection'; } return result; - }; + } /** * Checks if polygon intersects another polygon * @static * @param {Array} points1 * @param {Array} points2 - * @return {fabric.Intersection} + * @return {Intersection} */ - fabric.Intersection.intersectPolygonPolygon = function (points1, points2) { - var result = new Intersection(), - length = points1.length, i; + static intersectPolygonPolygon(points1, points2) { + const result = new Intersection(), + length = points1.length; - for (i = 0; i < length; i++) { - var a1 = points1[i], - a2 = points1[(i + 1) % length], - inter = Intersection.intersectLinePolygon(a1, a2, points2); + for (let i = 0; i < length; i++) { + const a1 = points1[i], + a2 = points1[(i + 1) % length], + inter = Intersection.intersectLinePolygon(a1, a2, points2); result.appendPoints(inter.points); } @@ -131,7 +125,7 @@ import { Point } from './point.class'; result.status = 'Intersection'; } return result; - }; + } /** * Checks if polygon intersects rectangle @@ -139,18 +133,18 @@ import { Point } from './point.class'; * @param {Array} points * @param {Point} r1 * @param {Point} r2 - * @return {fabric.Intersection} + * @return {Intersection} */ - fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) { - var min = r1.min(r2), - max = r1.max(r2), - topRight = new Point(max.x, min.y), - bottomLeft = new Point(min.x, max.y), - inter1 = Intersection.intersectLinePolygon(min, topRight, points), - inter2 = Intersection.intersectLinePolygon(topRight, max, points), - inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), - inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), - result = new Intersection(); + static intersectPolygonRectangle(points, r1, r2) { + const min = r1.min(r2), + max = r1.max(r2), + topRight = new Point(max.x, min.y), + bottomLeft = new Point(min.x, max.y), + inter1 = Intersection.intersectLinePolygon(min, topRight, points), + inter2 = Intersection.intersectLinePolygon(topRight, max, points), + inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), + inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), + result = new Intersection(); result.appendPoints(inter1.points); result.appendPoints(inter2.points); @@ -161,6 +155,8 @@ import { Point } from './point.class'; result.status = 'Intersection'; } return result; - }; + } + +} -})(typeof exports !== 'undefined' ? exports : window); +fabric.Intersection = Intersection; \ No newline at end of file From 59a61079d2c3501c7c01a89d32f6088398864b20 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Thu, 4 Aug 2022 17:46:21 +0300 Subject: [PATCH 04/22] iports --- src/mixins/object_geometry.mixin.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mixins/object_geometry.mixin.ts b/src/mixins/object_geometry.mixin.ts index ef586e57eca..3b015ce3164 100644 --- a/src/mixins/object_geometry.mixin.ts +++ b/src/mixins/object_geometry.mixin.ts @@ -1,4 +1,5 @@ //@ts-nocheck +import { Intersection } from '../intersection.class'; import { Point } from '../point.class'; (function(global) { @@ -235,7 +236,7 @@ import { Point } from '../point.class'; * @return {Boolean} true if object intersects with another object */ intersectsWithObject: function(other, absolute, calculate) { - var intersection = fabric.Intersection.intersectPolygonPolygon( + var intersection = Intersection.intersectPolygonPolygon( this.getCoords(absolute, calculate), other.getCoords(absolute, calculate) ); From 8f492aee2160695a82539ad86e883a4c3295a60a Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Thu, 4 Aug 2022 18:00:24 +0300 Subject: [PATCH 05/22] rename --- src/intersection.class.ts | 9 +++++---- test/unit/intersection.js | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index c23ce1deef1..1ace8aea399 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -39,8 +39,9 @@ export class Intersection { /** - * Checks if one line intersects another - * TODO: rename in intersectSegmentSegment + * Checks if a segment intersects another\ + * As opposed to an infinite line, a segment is limited to the points that define it + * meaning that this method checks intersection **ONLY** between the given points * @static * @param {Point} a1 * @param {Point} a2 @@ -48,7 +49,7 @@ export class Intersection { * @param {Point} b2 * @return {Intersection} */ - static intersectLineLine(a1, a2, b1, b2) { + static intersectSegmentSegment(a1, a2, b1, b2) { let result, uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), @@ -93,7 +94,7 @@ export class Intersection { for (let i = 0; i < length; i++) { b1 = points[i]; b2 = points[(i + 1) % length]; - inter = Intersection.intersectLineLine(a1, a2, b1, b2); + inter = Intersection.intersectSegmentSegment(a1, a2, b1, b2); result.appendPoints(inter.points); } diff --git a/test/unit/intersection.js b/test/unit/intersection.js index 8b93da9244a..1357fac51d8 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -41,47 +41,47 @@ assert.equal(intersection.points.length, 2, 'now intersection contains 2 points'); }); - QUnit.test('intersectLineLine simple intersection', function(assert) { + QUnit.test('intersectSegmentSegment simple intersection', function(assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(10,10), p3 = new fabric.Point(0, 10), p4 = new fabric.Point(10, 0), - intersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); - assert.ok(typeof fabric.Intersection.intersectLineLine === 'function', 'has intersectLineLine function'); + intersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4); + assert.ok(typeof fabric.Intersection.intersectSegmentSegment === 'function', 'has intersectSegmentSegment function'); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, 'Intersection', 'it return a intersection result'); assert.deepEqual(intersection.points[0], new fabric.Point(5, 5), 'intersect in 5,5'); }); - QUnit.test('intersectLineLine parallel', function(assert) { + QUnit.test('intersectSegmentSegment parallel', function(assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(0,10), p3 = new fabric.Point(10, 0), p4 = new fabric.Point(10, 10), - intersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); + intersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, 'Parallel', 'it return a Parallel result'); assert.deepEqual(intersection.points, [], 'no point of intersections'); }); - QUnit.test('intersectLineLine coincident', function(assert) { + QUnit.test('intersectSegmentSegment coincident', function(assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(0, 10), p3 = new fabric.Point(0, 0), p4 = new fabric.Point(0, 10), - intersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); + intersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, 'Coincident', 'it return a Coincident result'); assert.deepEqual(intersection.points, [], 'no point of intersections'); }); - QUnit.test('intersectLineLine coincident but different', function(assert) { + QUnit.test('intersectSegmentSegment coincident but different', function(assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(0, 10), p3 = new fabric.Point(0, 1), p4 = new fabric.Point(0, 9), - intersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); + intersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, 'Coincident', 'it return a Coincident result'); assert.deepEqual(intersection.points, [], 'no point of intersections'); }); - QUnit.test('intersectLineLine no intersect', function(assert) { + QUnit.test('intersectSegmentSegment no intersect', function(assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(0,10), p3 = new fabric.Point(10, 0), p4 = new fabric.Point(1, 10), - intersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); + intersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, undefined, 'it return a undefined status result'); assert.deepEqual(intersection.points, [], 'no point of intersections'); From 7c17d24cfbbc31930dc796421f187ec7750e54f3 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Thu, 4 Aug 2022 18:06:44 +0300 Subject: [PATCH 06/22] Update intersection.class.ts --- src/intersection.class.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index 1ace8aea399..0bd6756ff73 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -10,6 +10,8 @@ export class Intersection { points: Point[] + status?: IntersectionType + constructor(status?: IntersectionType) { this.status = status; this.points = []; @@ -50,8 +52,8 @@ export class Intersection { * @return {Intersection} */ static intersectSegmentSegment(a1, a2, b1, b2) { - let result, - uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), + let result; + const uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); if (uB !== 0) { From 7cec8913ae9bc6380f6585b4eb8bee1d87831ed0 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 05:37:16 +0300 Subject: [PATCH 07/22] rename --- src/intersection.class.ts | 13 ++++++------- test/unit/intersection.js | 18 +++++++++--------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index 0bd6756ff73..4cf29355fa7 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -80,7 +80,6 @@ export class Intersection { /** * Checks if line intersects polygon - * TODO: rename in intersectSegmentPolygon * fix detection of coincident * @static * @param {Point} a1 @@ -88,7 +87,7 @@ export class Intersection { * @param {Array} points * @return {Intersection} */ - static intersectLinePolygon(a1, a2, points) { + static intersectSegmentPolygon(a1, a2, points) { const result = new Intersection(), length = points.length; let b1, b2, inter; @@ -120,7 +119,7 @@ export class Intersection { for (let i = 0; i < length; i++) { const a1 = points1[i], a2 = points1[(i + 1) % length], - inter = Intersection.intersectLinePolygon(a1, a2, points2); + inter = Intersection.intersectSegmentPolygon(a1, a2, points2); result.appendPoints(inter.points); } @@ -143,10 +142,10 @@ export class Intersection { max = r1.max(r2), topRight = new Point(max.x, min.y), bottomLeft = new Point(min.x, max.y), - inter1 = Intersection.intersectLinePolygon(min, topRight, points), - inter2 = Intersection.intersectLinePolygon(topRight, max, points), - inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points), - inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points), + inter1 = Intersection.intersectSegmentPolygon(min, topRight, points), + inter2 = Intersection.intersectSegmentPolygon(topRight, max, points), + inter3 = Intersection.intersectSegmentPolygon(max, bottomLeft, points), + inter4 = Intersection.intersectSegmentPolygon(bottomLeft, min, points), result = new Intersection(); result.appendPoints(inter1.points); diff --git a/test/unit/intersection.js b/test/unit/intersection.js index 1357fac51d8..d282a7d5178 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -87,46 +87,46 @@ assert.deepEqual(intersection.points, [], 'no point of intersections'); }); - QUnit.test('intersectLinePolygon', function(assert) { + QUnit.test('intersectSegmentPolygon', function(assert) { var p1 = new fabric.Point(0, 5), p2 = new fabric.Point(10, 5), p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), p5 = new fabric.Point(8, 10), points = [p3, p4, p5], - intersection = fabric.Intersection.intersectLinePolygon(p1, p2, points); + intersection = fabric.Intersection.intersectSegmentPolygon(p1, p2, points); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); - assert.ok(typeof fabric.Intersection.intersectLinePolygon === 'function', 'has intersectLinePolygon function'); + assert.ok(typeof fabric.Intersection.intersectSegmentPolygon === 'function', 'has intersectSegmentPolygon function'); assert.equal(intersection.status, 'Intersection', 'it return a Intersection result'); assert.equal(intersection.points.length, 2, '2 points of intersections'); assert.deepEqual(intersection.points[0], new fabric.Point(3.5, 5), 'intersect in 3.5 ,5'); assert.deepEqual(intersection.points[1], new fabric.Point(6.5, 5), 'intersect in 6.5 ,5'); }); - QUnit.test('intersectLinePolygon in one point', function(assert) { + QUnit.test('intersectSegmentPolygon in one point', function(assert) { var p1 = new fabric.Point(0, 5), p2 = new fabric.Point(5, 5), p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), p5 = new fabric.Point(8, 10), points = [p3, p4, p5], - intersection = fabric.Intersection.intersectLinePolygon(p1, p2, points); + intersection = fabric.Intersection.intersectSegmentPolygon(p1, p2, points); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, 'Intersection', 'it return a Intersection result'); assert.equal(intersection.points.length, 1, '1 points of intersections'); assert.deepEqual(intersection.points[0], new fabric.Point(3.5, 5), 'intersect in 3.5 ,5'); }); - QUnit.test('intersectLinePolygon in one point', function(assert) { + QUnit.test('intersectSegmentPolygon in one point', function(assert) { var p1 = new fabric.Point(0, 5), p2 = new fabric.Point(3, 5), p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), p5 = new fabric.Point(8, 10), points = [p3, p4, p5], - intersection = fabric.Intersection.intersectLinePolygon(p1, p2, points); + intersection = fabric.Intersection.intersectSegmentPolygon(p1, p2, points); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, undefined, 'it return a undefined result'); assert.equal(intersection.points.length, 0, '0 points of intersections'); }); - QUnit.test('intersectLinePolygon on a polygon segment', function(assert) { + QUnit.test('intersectSegmentPolygon on a polygon segment', function(assert) { //TODO: fix this. it should return coincident. var p1 = new fabric.Point(1, 10), p2 = new fabric.Point(9, 10), p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), p5 = new fabric.Point(8, 10), points = [p3, p4, p5], - intersection = fabric.Intersection.intersectLinePolygon(p1, p2, points); + intersection = fabric.Intersection.intersectSegmentPolygon(p1, p2, points); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, 'Intersection', 'it return a Intersection result'); assert.equal(intersection.points.length, 2, '2 points of intersections'); From 7aa20faf1cc82e77884a0e5281fb9c80cc141ece Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 06:52:39 +0300 Subject: [PATCH 08/22] intersectLineLine --- src/intersection.class.ts | 37 +++++++++++++++++++++++++++++++++---- test/unit/intersection.js | 23 +++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index 4cf29355fa7..a6adf01d30e 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -6,6 +6,20 @@ import { fabric } from '../HEADER'; type IntersectionType = 'Intersection' | 'Coincident' | 'Parallel'; +/** + * **Assuming `T`, `A`, `B` are points on the same line**, + * check if `T` is contained in `[A, B]` by comparing the direction of the vectors from `T` to `A` and `B` + * @param T + * @param A + * @param B + * @returns + */ +const isContainedInInterval = (T: Point, A: Point, B: Point) => { + const TA = new Point(T).subtract(A); + const TB = new Point(T).subtract(B); + return Math.sign(TA.x) !== Math.sign(TB.x) || Math.sign(TA.y) !== Math.sign(TB.y); +} + export class Intersection { points: Point[] @@ -39,7 +53,6 @@ export class Intersection { return this; } - /** * Checks if a segment intersects another\ * As opposed to an infinite line, a segment is limited to the points that define it @@ -51,7 +64,21 @@ export class Intersection { * @param {Point} b2 * @return {Intersection} */ - static intersectSegmentSegment(a1, a2, b1, b2) { + static intersectSegmentSegment(a1, a2, b1, b2) { + return Intersection.intersectLineLine(a1, a2, b1, b2, false); + } + + /** + * Checks if a line intersects another + * @static + * @param {Point} a1 + * @param {Point} a2 + * @param {Point} b1 + * @param {Point} b2 + * @param {boolean} [infinite=true] check segment intersection by passing `false` + * @return {Intersection} + */ + static intersectLineLine(a1, a2, b1, b2, infinite = true) { let result; const uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), @@ -59,7 +86,7 @@ export class Intersection { if (uB !== 0) { const ua = uaT / uB, ub = ubT / uB; - if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { + if (infinite || (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1)) { result = new Intersection('Intersection'); result.appendPoint(new Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); } @@ -69,7 +96,9 @@ export class Intersection { } else { if (uaT === 0 || ubT === 0) { - result = new Intersection('Coincident'); + const segmentsCoincide = infinite || isContainedInInterval(a1, b1, b2) || isContainedInInterval(a2, b1, b2) + || isContainedInInterval(b1, a1, a2) || isContainedInInterval(b2, a1, a2); + result = new Intersection(segmentsCoincide ? 'Coincident' : undefined); } else { result = new Intersection('Parallel'); diff --git a/test/unit/intersection.js b/test/unit/intersection.js index d282a7d5178..15728fbc182 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -51,6 +51,16 @@ assert.deepEqual(intersection.points[0], new fabric.Point(5, 5), 'intersect in 5,5'); }); + QUnit.test('intersectLineLine intersection', function (assert) { + var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(-10, -10), + p3 = new fabric.Point(0, 10), p4 = new fabric.Point(10, 0), + intersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); + assert.ok(typeof fabric.Intersection.intersectSegmentSegment === 'function', 'has intersectSegmentSegment function'); + assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(intersection.status, 'Intersection', 'it return a intersection result'); + assert.deepEqual(intersection.points[0], new fabric.Point(5, 5), 'intersect in 5,5'); + }); + QUnit.test('intersectSegmentSegment parallel', function(assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(0,10), p3 = new fabric.Point(10, 0), p4 = new fabric.Point(10, 10), @@ -78,6 +88,19 @@ assert.deepEqual(intersection.points, [], 'no point of intersections'); }); + QUnit.test('intersectSegmentSegment no coincident, intersectLineLine infinite coincident', function (assert) { + var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(0, 10), + p3 = new fabric.Point(0, 20), p4 = new fabric.Point(0, 15), + segmentIntersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4), + infiniteIntersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); + assert.ok(segmentIntersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(segmentIntersection.status, undefined, 'it return no result'); + assert.deepEqual(segmentIntersection.points, [], 'no point of intersections'); + assert.ok(infiniteIntersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(infiniteIntersection.status, 'Coincident', 'it return a Coincident result'); + assert.deepEqual(infiniteIntersection.points, [], 'no point of intersections'); + }); + QUnit.test('intersectSegmentSegment no intersect', function(assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(0,10), p3 = new fabric.Point(10, 0), p4 = new fabric.Point(1, 10), From 91fb5eb0fb99d5bdd940ca0cfff3a87b74f3fa6f Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 07:26:51 +0300 Subject: [PATCH 09/22] fix(): polygon line coincident --- src/intersection.class.ts | 74 ++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index a6adf01d30e..0e7f10385f5 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -44,7 +44,7 @@ export class Intersection { /** * Appends points to intersection - * @param {Array} points + * @param {Point[]} points * @return {Intersection} thisArg * @chainable */ @@ -53,21 +53,6 @@ export class Intersection { return this; } - /** - * Checks if a segment intersects another\ - * As opposed to an infinite line, a segment is limited to the points that define it - * meaning that this method checks intersection **ONLY** between the given points - * @static - * @param {Point} a1 - * @param {Point} a2 - * @param {Point} b1 - * @param {Point} b2 - * @return {Intersection} - */ - static intersectSegmentSegment(a1, a2, b1, b2) { - return Intersection.intersectLineLine(a1, a2, b1, b2, false); - } - /** * Checks if a line intersects another * @static @@ -107,38 +92,70 @@ export class Intersection { return result; } + + /** + * Checks if a segment intersects another + * @see {@link intersectLineLine} for line intersection + * @static + * @param {Point} a1 + * @param {Point} a2 + * @param {Point} b1 + * @param {Point} b2 + * @return {Intersection} + */ + static intersectSegmentSegment(a1, a2, b1, b2) { + return Intersection.intersectLineLine(a1, a2, b1, b2, false); + } + /** * Checks if line intersects polygon * fix detection of coincident * @static * @param {Point} a1 * @param {Point} a2 - * @param {Array} points + * @param {Point[]} points + * @param {boolean} [infinite=true] check segment intersection by passing `false` * @return {Intersection} */ - static intersectSegmentPolygon(a1, a2, points) { - const result = new Intersection(), - length = points.length; - let b1, b2, inter; + static intersectLinePolygon(a1, a2, points, infinite = true) { + const result = new Intersection(); + const length = points.length; - for (let i = 0; i < length; i++) { + for (let i = 0, b1, b2, inter; i < length; i++) { b1 = points[i]; b2 = points[(i + 1) % length]; - inter = Intersection.intersectSegmentSegment(a1, a2, b1, b2); - + inter = Intersection.intersectLineLine(a1, a2, b1, b2, infinite); + if (inter.status === 'Coincident') { + return inter; + } result.appendPoints(inter.points); } + if (result.points.length > 0) { result.status = 'Intersection'; } + return result; } + /** + * Checks if segment intersects polygon + * fix detection of coincident + * @static + * @param {Point} a1 + * @param {Point} a2 + * @param {Point[]} points + * @return {Intersection} + */ + static intersectSegmentPolygon(a1, a2, points) { + return Intersection.intersectLinePolygon(a1, a2, points, false); + } + /** * Checks if polygon intersects another polygon * @static - * @param {Array} points1 - * @param {Array} points2 + * @param {Point[]} points1 + * @param {Point[]} points2 * @return {Intersection} */ static intersectPolygonPolygon(points1, points2) { @@ -149,19 +166,20 @@ export class Intersection { const a1 = points1[i], a2 = points1[(i + 1) % length], inter = Intersection.intersectSegmentPolygon(a1, a2, points2); - result.appendPoints(inter.points); } + if (result.points.length > 0) { result.status = 'Intersection'; } + return result; } /** * Checks if polygon intersects rectangle * @static - * @param {Array} points + * @param {Point[]} points * @param {Point} r1 * @param {Point} r2 * @return {Intersection} From d3ac3f3292cd535507412e50cc43226890d4930f Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 07:27:02 +0300 Subject: [PATCH 10/22] Update intersection.js --- test/unit/intersection.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/unit/intersection.js b/test/unit/intersection.js index 15728fbc182..fa7ec77364e 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -145,16 +145,13 @@ }); QUnit.test('intersectSegmentPolygon on a polygon segment', function(assert) { - //TODO: fix this. it should return coincident. var p1 = new fabric.Point(1, 10), p2 = new fabric.Point(9, 10), p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), p5 = new fabric.Point(8, 10), points = [p3, p4, p5], intersection = fabric.Intersection.intersectSegmentPolygon(p1, p2, points); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); - assert.equal(intersection.status, 'Intersection', 'it return a Intersection result'); - assert.equal(intersection.points.length, 2, '2 points of intersections'); - assert.deepEqual(intersection.points[0], new fabric.Point(2, 10), 'intersect in 2, 10'); - assert.deepEqual(intersection.points[1], new fabric.Point(8, 10), 'intersect in 8, 10'); + assert.equal(intersection.status, 'Coincident', 'it return a Intersection result'); + assert.equal(intersection.points.length, 0, 'infinte points of intersections'); }); QUnit.test('intersectPolygonPolygon not intersecting', function(assert) { From 578717ea5ec48c8fc3fc05b1d17e92c50bdd66e6 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 07:30:30 +0300 Subject: [PATCH 11/22] fixed! --- src/intersection.class.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index 0e7f10385f5..6ab0780a71b 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -109,7 +109,6 @@ export class Intersection { /** * Checks if line intersects polygon - * fix detection of coincident * @static * @param {Point} a1 * @param {Point} a2 From 5574cb2c1e7ce700b4a571cbd60beee27fda478d Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 08:49:03 +0300 Subject: [PATCH 12/22] more work --- src/intersection.class.ts | 68 +++++++++++++++++++---------- test/unit/intersection.js | 92 ++++++++++++++++++++++++++++++++++----- 2 files changed, 126 insertions(+), 34 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index 6ab0780a71b..4fa296077bd 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -63,7 +63,7 @@ export class Intersection { * @param {boolean} [infinite=true] check segment intersection by passing `false` * @return {Intersection} */ - static intersectLineLine(a1, a2, b1, b2, infinite = true) { + static intersectLineLine(a1, a2, b1, b2, aIinfinite = true, bIinfinite = true) { let result; const uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), @@ -71,7 +71,7 @@ export class Intersection { if (uB !== 0) { const ua = uaT / uB, ub = ubT / uB; - if (infinite || (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1)) { + if ((aIinfinite || (0 <= ua && ua <= 1)) && (bIinfinite || (0 <= ub && ub <= 1))) { result = new Intersection('Intersection'); result.appendPoint(new Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); } @@ -81,7 +81,8 @@ export class Intersection { } else { if (uaT === 0 || ubT === 0) { - const segmentsCoincide = infinite || isContainedInInterval(a1, b1, b2) || isContainedInInterval(a2, b1, b2) + const segmentsCoincide = aIinfinite || bIinfinite + || isContainedInInterval(a1, b1, b2) || isContainedInInterval(a2, b1, b2) || isContainedInInterval(b1, a1, a2) || isContainedInInterval(b2, a1, a2); result = new Intersection(segmentsCoincide ? 'Coincident' : undefined); } @@ -92,6 +93,19 @@ export class Intersection { return result; } + /** + * Checks if a segment intersects another + * @see {@link intersectLineLine} for line intersection + * @static + * @param {Point} s1 + * @param {Point} s2 + * @param {Point} l1 + * @param {Point} l2 + * @return {Intersection} + */ + static intersectSegmentLine(s1, s2, l1, l2) { + return Intersection.intersectLineLine(s1, s2, l1, l2, false, true); + } /** * Checks if a segment intersects another @@ -104,7 +118,7 @@ export class Intersection { * @return {Intersection} */ static intersectSegmentSegment(a1, a2, b1, b2) { - return Intersection.intersectLineLine(a1, a2, b1, b2, false); + return Intersection.intersectLineLine(a1, a2, b1, b2, false, false); } /** @@ -123,7 +137,7 @@ export class Intersection { for (let i = 0, b1, b2, inter; i < length; i++) { b1 = points[i]; b2 = points[(i + 1) % length]; - inter = Intersection.intersectLineLine(a1, a2, b1, b2, infinite); + inter = Intersection.intersectLineLine(a1, a2, b1, b2, infinite, false); if (inter.status === 'Coincident') { return inter; } @@ -139,7 +153,6 @@ export class Intersection { /** * Checks if segment intersects polygon - * fix detection of coincident * @static * @param {Point} a1 * @param {Point} a2 @@ -160,16 +173,31 @@ export class Intersection { static intersectPolygonPolygon(points1, points2) { const result = new Intersection(), length = points1.length; + const coincidents = []; for (let i = 0; i < length; i++) { const a1 = points1[i], a2 = points1[(i + 1) % length], inter = Intersection.intersectSegmentPolygon(a1, a2, points2); - result.appendPoints(inter.points); + if (inter.status === 'Coincident') { + coincidents.push(inter); + result.appendPoints([a1, a2]); + } + else { + result.appendPoints(inter.points); + } } - if (result.points.length > 0) { + if (coincidents.length > 0 && coincidents.length === points1.length && coincidents.length === points2.length) { + return new Intersection('Coincident'); + } + else if (result.points.length > 0) { result.status = 'Intersection'; + if (coincidents.length > 0) { + result.points = result.points.reduce((all, curr) => { + return all.every(p => !p.eq(curr)) ? all.concat(curr) : all; + }, []); + } } return result; @@ -187,22 +215,14 @@ export class Intersection { const min = r1.min(r2), max = r1.max(r2), topRight = new Point(max.x, min.y), - bottomLeft = new Point(min.x, max.y), - inter1 = Intersection.intersectSegmentPolygon(min, topRight, points), - inter2 = Intersection.intersectSegmentPolygon(topRight, max, points), - inter3 = Intersection.intersectSegmentPolygon(max, bottomLeft, points), - inter4 = Intersection.intersectSegmentPolygon(bottomLeft, min, points), - result = new Intersection(); - - result.appendPoints(inter1.points); - result.appendPoints(inter2.points); - result.appendPoints(inter3.points); - result.appendPoints(inter4.points); - - if (result.points.length > 0) { - result.status = 'Intersection'; - } - return result; + bottomLeft = new Point(min.x, max.y); + + return Intersection.intersectPolygonPolygon(points, [ + min, + topRight, + max, + bottomLeft + ]); } } diff --git a/test/unit/intersection.js b/test/unit/intersection.js index fa7ec77364e..9a84062b013 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -41,20 +41,33 @@ assert.equal(intersection.points.length, 2, 'now intersection contains 2 points'); }); - QUnit.test('intersectSegmentSegment simple intersection', function(assert) { - var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(10,10), - p3 = new fabric.Point(0, 10), p4 = new fabric.Point(10, 0), - intersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4); - assert.ok(typeof fabric.Intersection.intersectSegmentSegment === 'function', 'has intersectSegmentSegment function'); + QUnit.test('intersectLineLine intersection', function (assert) { + var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(-10, -10), + p3 = new fabric.Point(0, 10), p4 = new fabric.Point(10, 0), + intersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, 'Intersection', 'it return a intersection result'); assert.deepEqual(intersection.points[0], new fabric.Point(5, 5), 'intersect in 5,5'); }); - QUnit.test('intersectLineLine intersection', function (assert) { + QUnit.test('intersectSegmentLine intersection', function (assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(-10, -10), p3 = new fabric.Point(0, 10), p4 = new fabric.Point(10, 0), - intersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); + intersection1 = fabric.Intersection.intersectSegmentLine(p1, p2, p3, p4), + intersection2 = fabric.Intersection.intersectSegmentLine(p4, p3, p2, p1); + assert.ok(intersection1 instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(intersection1.status, undefined, 'no result'); + assert.equal(intersection1.points.length, 0, 'no result'); + assert.ok(intersection2 instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(intersection2.status, 'Intersection', 'Intersection result'); + assert.equal(intersection2.points.length, 1, 'has result'); + assert.deepEqual(intersection2.points[0], new fabric.Point(5, 5), 'intersect in 5,5'); + }); + + QUnit.test('intersectSegmentSegment simple intersection', function(assert) { + var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(10,10), + p3 = new fabric.Point(0, 10), p4 = new fabric.Point(10, 0), + intersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4); assert.ok(typeof fabric.Intersection.intersectSegmentSegment === 'function', 'has intersectSegmentSegment function'); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, 'Intersection', 'it return a intersection result'); @@ -88,14 +101,18 @@ assert.deepEqual(intersection.points, [], 'no point of intersections'); }); - QUnit.test('intersectSegmentSegment no coincident, intersectLineLine infinite coincident', function (assert) { + QUnit.test('intersectSegmentSegment no coincident, intersectLineLine coincident', function (assert) { var p1 = new fabric.Point(0, 0), p2 = new fabric.Point(0, 10), p3 = new fabric.Point(0, 20), p4 = new fabric.Point(0, 15), segmentIntersection = fabric.Intersection.intersectSegmentSegment(p1, p2, p3, p4), + segLineIntersection = fabric.Intersection.intersectSegmentLine(p1, p2, p3, p4), infiniteIntersection = fabric.Intersection.intersectLineLine(p1, p2, p3, p4); assert.ok(segmentIntersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(segmentIntersection.status, undefined, 'it return no result'); assert.deepEqual(segmentIntersection.points, [], 'no point of intersections'); + assert.ok(segLineIntersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(segLineIntersection.status, 'Coincident', 'it return a Coincident result'); + assert.deepEqual(segLineIntersection.points, [], 'no point of intersections'); assert.ok(infiniteIntersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(infiniteIntersection.status, 'Coincident', 'it return a Coincident result'); assert.deepEqual(infiniteIntersection.points, [], 'no point of intersections'); @@ -134,14 +151,14 @@ assert.deepEqual(intersection.points[0], new fabric.Point(3.5, 5), 'intersect in 3.5 ,5'); }); - QUnit.test('intersectSegmentPolygon in one point', function(assert) { + QUnit.test('intersectSegmentPolygonno intersection', function(assert) { var p1 = new fabric.Point(0, 5), p2 = new fabric.Point(3, 5), p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), p5 = new fabric.Point(8, 10), points = [p3, p4, p5], intersection = fabric.Intersection.intersectSegmentPolygon(p1, p2, points); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(intersection.status, undefined, 'it return a undefined result'); - assert.equal(intersection.points.length, 0, '0 points of intersections'); + assert.equal(intersection.points.length, 0, '0 points of intersections, closet intersection is (3.5, 5)'); }); QUnit.test('intersectSegmentPolygon on a polygon segment', function(assert) { @@ -154,6 +171,38 @@ assert.equal(intersection.points.length, 0, 'infinte points of intersections'); }); + QUnit.test.skip('intersectLinePolygon one point', function (assert) { + var p1 = new fabric.Point(0, 1), p2 = new fabric.Point(0, 0), + p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), + p5 = new fabric.Point(8, 10), points = [p3, p4, p5], + intersection = fabric.Intersection.intersectLinePolygon(p1, p2, points); + assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(intersection.status, 'Intersection', 'it return an Intersection result'); + assert.equal(intersection.points.length, 1, '1 point of intersection'); + assert.deepEqual(intersection.points, [new fabric.Point(5, 0)], 'intersection points should match'); + }); + + QUnit.test('intersectLinePolygon', function (assert) { + var p1 = new fabric.Point(0, 5), p2 = new fabric.Point(3, 5), + p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), + p5 = new fabric.Point(8, 10), points = [p3, p4, p5], + intersection = fabric.Intersection.intersectLinePolygon(p1, p2, points); + assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(intersection.status, 'Intersection', 'it return an Intersection result'); + assert.equal(intersection.points.length, 2, '2 points of intersection'); + assert.deepEqual(intersection.points, [new fabric.Point(3.5, 5), new fabric.Point(6.5, 5)], 'intersection points should match'); + }); + + QUnit.test('intersectLinePolygon on a polygon segment', function (assert) { + var p1 = new fabric.Point(1, 10), p2 = new fabric.Point(9, 10), + p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), + p5 = new fabric.Point(8, 10), points = [p3, p4, p5], + intersection = fabric.Intersection.intersectLinePolygon(p1, p2, points); + assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(intersection.status, 'Coincident', 'it return a Intersection result'); + assert.equal(intersection.points.length, 0, 'infinte points of intersections'); + }); + QUnit.test('intersectPolygonPolygon not intersecting', function(assert) { var p3b = new fabric.Point(50, 0), p4b = new fabric.Point(20, 100), p5b = new fabric.Point(80, 100), pointsb = [p3b, p4b, p5b], @@ -209,4 +258,27 @@ assert.equal(intersection.status, undefined, 'it return a Intersection result'); assert.equal(intersection.points.length, 0, '0 points of intersections'); }); + + QUnit.test('intersectPolygonPolygon coincident', function (assert) { + const points = [ + new fabric.Point(0, 0), + new fabric.Point(10, 0), + new fabric.Point(15, 5), + new fabric.Point(10, 10), + new fabric.Point(-5, 5), + ]; + assert.ok(typeof fabric.Intersection.intersectPolygonRectangle === 'function', 'has intersectPolygonPolygon function'); + + let intersection = fabric.Intersection.intersectPolygonPolygon(points, points.concat()); + assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); + assert.equal(intersection.status, 'Coincident', 'it return a Coincident result'); + assert.equal(intersection.points.length, 0, '0 points of intersections'); + + // though actually this is a coincident I defined it to return Intersection + // because we don't want to determine if the polygons differ in sides (points can be arranged in a differnet order) + intersection = fabric.Intersection.intersectPolygonPolygon(points, points.concat(new fabric.Point(0, 0))); + assert.equal(intersection.status, 'Intersection', 'it return a Intersection result'); + assert.equal(intersection.points.length, points.length, 'all points intersect'); + assert.deepEqual(intersection.points, points, 'result should equal points'); + }); })(); From 4ff248335dc4ff2f276a7a15df8f7b539672c6ba Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 08:52:45 +0300 Subject: [PATCH 13/22] fix intersectLinePolygon --- src/intersection.class.ts | 3 +++ test/unit/intersection.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index 4fa296077bd..f7fa3509b2f 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -146,6 +146,9 @@ export class Intersection { if (result.points.length > 0) { result.status = 'Intersection'; + result.points = result.points.reduce((all, curr) => { + return all.every(p => !p.eq(curr)) ? all.concat(curr) : all; + }, []); } return result; diff --git a/test/unit/intersection.js b/test/unit/intersection.js index 9a84062b013..fc00b325d86 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -171,8 +171,8 @@ assert.equal(intersection.points.length, 0, 'infinte points of intersections'); }); - QUnit.test.skip('intersectLinePolygon one point', function (assert) { - var p1 = new fabric.Point(0, 1), p2 = new fabric.Point(0, 0), + QUnit.test('intersectLinePolygon one point', function (assert) { + var p1 = new fabric.Point(1, 0), p2 = new fabric.Point(0, 0), p3 = new fabric.Point(5, 0), p4 = new fabric.Point(2, 10), p5 = new fabric.Point(8, 10), points = [p3, p4, p5], intersection = fabric.Intersection.intersectLinePolygon(p1, p2, points); From 46182f2fbe2ad52e570a1ea5e89f33f5f678c6fb Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 08:57:25 +0300 Subject: [PATCH 14/22] move unique points logic to appendPoint --- src/intersection.class.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index f7fa3509b2f..aafd109feef 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -12,7 +12,7 @@ type IntersectionType = 'Intersection' | 'Coincident' | 'Parallel'; * @param T * @param A * @param B - * @returns + * @returns true if `T` is contained */ const isContainedInInterval = (T: Point, A: Point, B: Point) => { const TA = new Point(T).subtract(A); @@ -38,7 +38,9 @@ export class Intersection { * @chainable */ appendPoint(point) { - this.points.push(point); + if (this.points.every(p => !p.eq(point))) { + this.points.push(point); + } return this; } @@ -49,7 +51,9 @@ export class Intersection { * @chainable */ appendPoints(points) { - this.points = this.points.concat(points); + this.points = this.points.concat(points.filter(point => { + return this.points.every(p => !p.eq(point)); + })); return this; } @@ -146,9 +150,6 @@ export class Intersection { if (result.points.length > 0) { result.status = 'Intersection'; - result.points = result.points.reduce((all, curr) => { - return all.every(p => !p.eq(curr)) ? all.concat(curr) : all; - }, []); } return result; @@ -196,11 +197,6 @@ export class Intersection { } else if (result.points.length > 0) { result.status = 'Intersection'; - if (coincidents.length > 0) { - result.points = result.points.reduce((all, curr) => { - return all.every(p => !p.eq(curr)) ? all.concat(curr) : all; - }, []); - } } return result; From 6c1120c2447eb39c2fc0ccfac1d4008b03e0409f Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 08:59:03 +0300 Subject: [PATCH 15/22] Update intersection.class.ts --- src/intersection.class.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index aafd109feef..4481b96f5fb 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -31,6 +31,10 @@ export class Intersection { this.points = []; } + private contains(point) { + return this.points.some(p => p.eq(point)); + } + /** * Appends a point to intersection * @param {Point} point @@ -38,7 +42,7 @@ export class Intersection { * @chainable */ appendPoint(point) { - if (this.points.every(p => !p.eq(point))) { + if (!this.contains(point)) { this.points.push(point); } return this; @@ -52,7 +56,7 @@ export class Intersection { */ appendPoints(points) { this.points = this.points.concat(points.filter(point => { - return this.points.every(p => !p.eq(point)); + return !this.contains(point); })); return this; } From 3a3e9022b1f40185e7c7de67bf66abda1ec3c734 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 09:05:01 +0300 Subject: [PATCH 16/22] Update intersection.class.ts --- src/intersection.class.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index 4481b96f5fb..5b984066897 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -31,7 +31,12 @@ export class Intersection { this.points = []; } - private contains(point) { + /** + * + * @param {Point} point + * @returns + */ + contains(point) { return this.points.some(p => p.eq(point)); } @@ -68,7 +73,8 @@ export class Intersection { * @param {Point} a2 * @param {Point} b1 * @param {Point} b2 - * @param {boolean} [infinite=true] check segment intersection by passing `false` + * @param {boolean} [aIinfinite=true] check intersection by passing `false` + * @param {boolean} [bIinfinite=true] check intersection by passing `false` * @return {Intersection} */ static intersectLineLine(a1, a2, b1, b2, aIinfinite = true, bIinfinite = true) { From 627c73d62f8c56da74a2b107e855ad43d7df61e6 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Fri, 5 Aug 2022 09:29:13 +0300 Subject: [PATCH 17/22] dep(): `appendPoint` `appendPoints` => `append` --- src/intersection.class.ts | 27 +++++++-------------------- test/unit/intersection.js | 16 +++------------- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index 5b984066897..ac202d64192 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -41,25 +41,12 @@ export class Intersection { } /** - * Appends a point to intersection - * @param {Point} point + * Appends points of intersection + * @param {...Point[]} points * @return {Intersection} thisArg * @chainable */ - appendPoint(point) { - if (!this.contains(point)) { - this.points.push(point); - } - return this; - } - - /** - * Appends points to intersection - * @param {Point[]} points - * @return {Intersection} thisArg - * @chainable - */ - appendPoints(points) { + private append(...points) { this.points = this.points.concat(points.filter(point => { return !this.contains(point); })); @@ -87,7 +74,7 @@ export class Intersection { ub = ubT / uB; if ((aIinfinite || (0 <= ua && ua <= 1)) && (bIinfinite || (0 <= ub && ub <= 1))) { result = new Intersection('Intersection'); - result.appendPoint(new Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); + result.append(new Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y))); } else { result = new Intersection(); @@ -155,7 +142,7 @@ export class Intersection { if (inter.status === 'Coincident') { return inter; } - result.appendPoints(inter.points); + result.append(...inter.points); } if (result.points.length > 0) { @@ -195,10 +182,10 @@ export class Intersection { inter = Intersection.intersectSegmentPolygon(a1, a2, points2); if (inter.status === 'Coincident') { coincidents.push(inter); - result.appendPoints([a1, a2]); + result.append(a1, a2); } else { - result.appendPoints(inter.points); + result.append(...inter.points); } } diff --git a/test/unit/intersection.js b/test/unit/intersection.js index fc00b325d86..54ef4e98186 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -20,21 +20,11 @@ assert.equal(intersection.status, status, 'constructor pass status value'); }); - QUnit.test('appendPoint', function(assert) { + QUnit.test('append', function(assert) { var point = new fabric.Point(1, 1); var intersection = new fabric.Intersection(); - assert.ok(typeof intersection.appendPoint === 'function', 'has appendPoint method'); - var returned = intersection.appendPoint(point); - assert.ok(returned instanceof fabric.Intersection, 'returns a fabric.Intersection'); - assert.equal(returned, intersection, 'is chainable'); - assert.equal(intersection.points.indexOf(point), 0, 'now intersection contain points'); - }); - - QUnit.test('appendPoints', function(assert) { - var point = new fabric.Point(1, 1); - var intersection = new fabric.Intersection(); - assert.ok(typeof intersection.appendPoints === 'function', 'has appendPoint method'); - var returned = intersection.appendPoints([point, point]); + assert.ok(typeof intersection.append === 'function', 'has appendPoint method'); + var returned = intersection.append(point, point); assert.ok(returned instanceof fabric.Intersection, 'returns a fabric.Intersection'); assert.equal(returned, intersection, 'is chainable'); assert.equal(intersection.points.indexOf(point), 0, 'now intersection contain points'); From 26fb94a978659f944c9e6faf44c92b79a3f89f54 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 8 Aug 2022 18:16:13 +0300 Subject: [PATCH 18/22] fix polygon coincident edge case case when polygons are the same, one has more points --- src/intersection.class.ts | 2 +- test/unit/intersection.js | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index ac202d64192..d18c69c673b 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -189,7 +189,7 @@ export class Intersection { } } - if (coincidents.length > 0 && coincidents.length === points1.length && coincidents.length === points2.length) { + if (coincidents.length > 0 && coincidents.length === points1.length) { return new Intersection('Coincident'); } else if (result.points.length > 0) { diff --git a/test/unit/intersection.js b/test/unit/intersection.js index 54ef4e98186..f2e80cd43b0 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -261,13 +261,22 @@ let intersection = fabric.Intersection.intersectPolygonPolygon(points, points.concat()); assert.ok(intersection instanceof fabric.Intersection, 'returns a fabric.Intersection'); - assert.equal(intersection.status, 'Coincident', 'it return a Coincident result'); - assert.equal(intersection.points.length, 0, '0 points of intersections'); + assert.equal(intersection.status, 'Coincident', 'Coincident result'); + assert.equal(intersection.points.length, 0, 'Coincident'); + assert.deepEqual(intersection.points, [], 'result should be empty'); - // though actually this is a coincident I defined it to return Intersection - // because we don't want to determine if the polygons differ in sides (points can be arranged in a differnet order) - intersection = fabric.Intersection.intersectPolygonPolygon(points, points.concat(new fabric.Point(0, 0))); - assert.equal(intersection.status, 'Intersection', 'it return a Intersection result'); + intersection = fabric.Intersection.intersectPolygonPolygon(points, points.concat(points[0].clone())); + assert.equal(intersection.status, 'Coincident', 'Coincident result'); + assert.equal(intersection.points.length, 0, 'Coincident'); + assert.deepEqual(intersection.points, [], 'result should be empty'); + + intersection = fabric.Intersection.intersectPolygonPolygon(points, points.concat(points[points.length - 1].clone())); + assert.equal(intersection.status, 'Coincident', 'Coincident result'); + assert.equal(intersection.points.length, 0, 'Coincident'); + assert.deepEqual(intersection.points, [], 'result should be empty'); + + intersection = fabric.Intersection.intersectPolygonPolygon(points, points.concat(points[1].clone())); + assert.equal(intersection.status, 'Intersection', 'it return a Coincident result'); assert.equal(intersection.points.length, points.length, 'all points intersect'); assert.deepEqual(intersection.points, points, 'result should equal points'); }); From 89f13c48b0d76deac286018e447c0e3e96bb71c9 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 8 Aug 2022 18:21:14 +0300 Subject: [PATCH 19/22] Update intersection.js --- test/unit/intersection.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/unit/intersection.js b/test/unit/intersection.js index f2e80cd43b0..a9948c9e109 100644 --- a/test/unit/intersection.js +++ b/test/unit/intersection.js @@ -276,8 +276,13 @@ assert.deepEqual(intersection.points, [], 'result should be empty'); intersection = fabric.Intersection.intersectPolygonPolygon(points, points.concat(points[1].clone())); - assert.equal(intersection.status, 'Intersection', 'it return a Coincident result'); + assert.equal(intersection.status, 'Intersection', 'Intersection result'); assert.equal(intersection.points.length, points.length, 'all points intersect'); assert.deepEqual(intersection.points, points, 'result should equal points'); + + intersection = fabric.Intersection.intersectPolygonPolygon(points, points.slice(0, -1)); + assert.equal(intersection.status, 'Intersection', 'Intersection result'); + assert.equal(intersection.points.length, points.length - 1, 'all points intersect accept the last'); + assert.deepEqual(intersection.points, points.slice(0, -1), 'result should equal points accept the last'); }); })(); From e94d62e4c0f2feb3ee62397478f0c3e957715960 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Wed, 17 Aug 2022 23:10:43 +0300 Subject: [PATCH 20/22] JSDOC --- src/intersection.class.ts | 52 ++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index d18c69c673b..c1c725af35c 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -60,8 +60,8 @@ export class Intersection { * @param {Point} a2 * @param {Point} b1 * @param {Point} b2 - * @param {boolean} [aIinfinite=true] check intersection by passing `false` - * @param {boolean} [bIinfinite=true] check intersection by passing `false` + * @param {boolean} [aIinfinite=true] check segment intersection by passing `false` + * @param {boolean} [bIinfinite=true] check segment intersection by passing `false` * @return {Intersection} */ static intersectLineLine(a1, a2, b1, b2, aIinfinite = true, bIinfinite = true) { @@ -95,13 +95,13 @@ export class Intersection { } /** - * Checks if a segment intersects another + * Checks if a segment intersects a line * @see {@link intersectLineLine} for line intersection * @static - * @param {Point} s1 - * @param {Point} s2 - * @param {Point} l1 - * @param {Point} l2 + * @param {Point} s1 boundary point of segment + * @param {Point} s2 other boundary point of segment + * @param {Point} l1 point on line + * @param {Point} l2 other point on line * @return {Intersection} */ static intersectSegmentLine(s1, s2, l1, l2) { @@ -112,10 +112,10 @@ export class Intersection { * Checks if a segment intersects another * @see {@link intersectLineLine} for line intersection * @static - * @param {Point} a1 - * @param {Point} a2 - * @param {Point} b1 - * @param {Point} b2 + * @param {Point} a1 boundary point of segment + * @param {Point} a2 other boundary point of segment + * @param {Point} b1 boundary point of segment + * @param {Point} b2 other boundary point of segment * @return {Intersection} */ static intersectSegmentSegment(a1, a2, b1, b2) { @@ -124,10 +124,14 @@ export class Intersection { /** * Checks if line intersects polygon + * + * @todo account for stroke + * * @static - * @param {Point} a1 - * @param {Point} a2 - * @param {Point[]} points + * @see {@link intersectSegmentPolygon} for segment intersection + * @param {Point} a1 point on line + * @param {Point} a2 other point on line + * @param {Point[]} points polygon points * @param {boolean} [infinite=true] check segment intersection by passing `false` * @return {Intersection} */ @@ -154,10 +158,14 @@ export class Intersection { /** * Checks if segment intersects polygon + * + * @todo account for stroke + * * @static - * @param {Point} a1 - * @param {Point} a2 - * @param {Point[]} points + * @see {@link intersectLinePolygon} for line intersection + * @param {Point} a1 boundary point of segment + * @param {Point} a2 other boundary point of segment + * @param {Point[]} points polygon points * @return {Intersection} */ static intersectSegmentPolygon(a1, a2, points) { @@ -166,6 +174,9 @@ export class Intersection { /** * Checks if polygon intersects another polygon + * + * @todo account for stroke + * * @static * @param {Point[]} points1 * @param {Point[]} points2 @@ -202,9 +213,10 @@ export class Intersection { /** * Checks if polygon intersects rectangle * @static - * @param {Point[]} points - * @param {Point} r1 - * @param {Point} r2 + * @see {@link intersectPolygonPolygon} for polygon intersection + * @param {Point[]} points polygon points + * @param {Point} r1 top left point of rect + * @param {Point} r2 bottom right point of rect * @return {Intersection} */ static intersectPolygonRectangle(points, r1, r2) { From 1df3ec29052d67f22207efd82b16e928e01b9179 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Wed, 17 Aug 2022 23:12:46 +0300 Subject: [PATCH 21/22] Update object_geometry.mixin.ts --- src/mixins/object_geometry.mixin.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mixins/object_geometry.mixin.ts b/src/mixins/object_geometry.mixin.ts index 79104685eba..648c869943a 100644 --- a/src/mixins/object_geometry.mixin.ts +++ b/src/mixins/object_geometry.mixin.ts @@ -243,6 +243,7 @@ import { Point } from '../point.class'; ); return intersection.status === 'Intersection' + || intersection.status === 'Coincident' || other.isContainedWithinObject(this, absolute, calculate) || this.isContainedWithinObject(other, absolute, calculate); }, From ecdb285877ef18b8997e504a55edb131f6a7ee96 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Wed, 17 Aug 2022 23:18:54 +0300 Subject: [PATCH 22/22] Update intersection.class.ts --- src/intersection.class.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/intersection.class.ts b/src/intersection.class.ts index c1c725af35c..2b6a14bd4eb 100644 --- a/src/intersection.class.ts +++ b/src/intersection.class.ts @@ -158,9 +158,6 @@ export class Intersection { /** * Checks if segment intersects polygon - * - * @todo account for stroke - * * @static * @see {@link intersectLinePolygon} for line intersection * @param {Point} a1 boundary point of segment