2020-01-19 00:45:17 +01:00
|
|
|
import GeometryPoint from "./GeometryPoint.js";
|
|
|
|
import GeometryStroke from "./GeometryStroke.js";
|
|
|
|
import GeometryPointCollection from "./GeometryPointCollection.js";
|
2020-01-22 22:50:45 +01:00
|
|
|
import GeometryLine from "./GeometryLine.js";
|
2020-01-19 00:45:17 +01:00
|
|
|
|
|
|
|
export default class GeometryRect
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @param x: float
|
|
|
|
* @param y: float
|
|
|
|
* @param width: float
|
|
|
|
* @param height: float
|
|
|
|
*/
|
|
|
|
constructor(x, y, width, height)
|
|
|
|
{
|
|
|
|
this.position = new GeometryPoint(x, y);
|
|
|
|
this.width = width;
|
|
|
|
this.height = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns if the given point is inside this rect.
|
|
|
|
*
|
|
|
|
* @param geometryPoint
|
|
|
|
* @returns {boolean|boolean}
|
|
|
|
*/
|
|
|
|
isContainingPoint(geometryPoint)
|
|
|
|
{
|
|
|
|
let containsHorizontally = geometryPoint.x >= this.position.x && geometryPoint.x <= this.position.x + this.width;
|
|
|
|
let containsVertically = geometryPoint.y >= this.position.y && geometryPoint.y <= this.position.y + this.height;
|
|
|
|
|
|
|
|
return containsHorizontally && containsVertically;
|
|
|
|
}
|
|
|
|
|
2020-01-22 22:50:45 +01:00
|
|
|
hasIntersectionWithRect(rect)
|
|
|
|
{
|
|
|
|
return this.getBorderIntersectonsWithRect(rect).getLength() > 0;
|
|
|
|
}
|
|
|
|
|
2020-01-19 00:45:17 +01:00
|
|
|
getBorderTop()
|
|
|
|
{
|
|
|
|
return new GeometryStroke(
|
|
|
|
new GeometryPoint(this.position.x, this.position.y),
|
|
|
|
new GeometryPoint(this.position.x + this.width, this.position.y)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
getBorderLeft()
|
|
|
|
{
|
|
|
|
return new GeometryStroke(
|
|
|
|
new GeometryPoint(this.position.x, this.position.y),
|
|
|
|
new GeometryPoint(this.position.x, this.position.y + this.height)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
getBorderRight()
|
|
|
|
{
|
|
|
|
return new GeometryStroke(
|
|
|
|
new GeometryPoint(this.position.x + this.width, this.position.y),
|
|
|
|
new GeometryPoint(this.position.x + this.width, this.position.y + this.height)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
getBorderBottom() {
|
|
|
|
return new GeometryStroke(
|
|
|
|
new GeometryPoint(this.position.x, this.position.y + this.height),
|
|
|
|
new GeometryPoint(this.position.x + this.width, this.position.y + this.height)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns all intersection points between this rect and a line.
|
|
|
|
*
|
|
|
|
* @param geometryLine
|
|
|
|
* @returns {GeometryPointCollection}
|
|
|
|
*/
|
|
|
|
getBorderIntersectionsWithLine(geometryLine)
|
|
|
|
{
|
|
|
|
let borders = [
|
|
|
|
this.getBorderTop(),
|
|
|
|
this.getBorderLeft(),
|
|
|
|
this.getBorderRight(),
|
|
|
|
this.getBorderBottom()
|
|
|
|
];
|
|
|
|
|
|
|
|
let intersections = new GeometryPointCollection();
|
|
|
|
|
|
|
|
borders.forEach(
|
|
|
|
(border) => {
|
|
|
|
let intersection = border.getIntersectionWithLine(geometryLine);
|
|
|
|
|
|
|
|
if (intersection !== null && this.isContainingPoint(intersection)) {
|
|
|
|
intersections.addGeometryPoint(intersection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
return intersections;
|
|
|
|
}
|
|
|
|
|
2020-01-22 22:50:45 +01:00
|
|
|
/**
|
|
|
|
* Returns the intersection points between the border lines and the given stroke.
|
|
|
|
*
|
|
|
|
* @param stroke
|
|
|
|
* @returns {GeometryPointCollection}
|
|
|
|
*/
|
2020-01-19 00:45:17 +01:00
|
|
|
getBorderIntersectionsWithStroke(stroke)
|
|
|
|
{
|
|
|
|
let borders = [
|
|
|
|
this.getBorderTop(),
|
|
|
|
this.getBorderLeft(),
|
|
|
|
this.getBorderRight(),
|
|
|
|
this.getBorderBottom()
|
|
|
|
];
|
|
|
|
|
|
|
|
let intersections = new GeometryPointCollection();
|
|
|
|
|
|
|
|
borders.forEach(
|
|
|
|
(border) => {
|
|
|
|
let intersection = border.getIntersectionWithStroke(stroke);
|
|
|
|
|
|
|
|
if (intersection !== null && this.isContainingPoint(intersection)) {
|
|
|
|
intersections.addGeometryPoint(intersection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
return intersections;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all intersections between this and another rect as point collection.
|
|
|
|
*
|
|
|
|
* @param rect GeometryRect
|
|
|
|
* @returns {GeometryPointCollection}
|
|
|
|
*/
|
|
|
|
getBorderIntersectonsWithRect(rect)
|
|
|
|
{
|
|
|
|
let intersections = new GeometryPointCollection();
|
|
|
|
|
|
|
|
let strokes = [
|
|
|
|
rect.getBorderTop(),
|
|
|
|
rect.getBorderLeft(),
|
|
|
|
rect.getBorderRight(),
|
|
|
|
rect.getBorderBottom(),
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
strokes.forEach(
|
|
|
|
(stroke) => {
|
|
|
|
this.getBorderIntersectionsWithStroke(stroke).forEach(
|
|
|
|
(point) => {
|
|
|
|
intersections.addGeometryPoint(point);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
return intersections;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the four points that define the edges of this rect.
|
|
|
|
*
|
|
|
|
* @returns {GeometryPointCollection}
|
|
|
|
*/
|
|
|
|
getRectanglePoints()
|
|
|
|
{
|
|
|
|
let collection = new GeometryPointCollection();
|
|
|
|
|
|
|
|
collection.addGeometryPoint(this.position);
|
|
|
|
collection.addGeometryPoint(new GeometryPoint(this.position.x + this.width, this.position.y));
|
|
|
|
collection.addGeometryPoint(new GeometryPoint(this.position.x, this.position.y + this.height));
|
|
|
|
collection.addGeometryPoint(new GeometryPoint(this.position.x + this.width, this.position.y + this.height));
|
|
|
|
|
|
|
|
return collection;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the intersection area between this and another rect as new rect or null.
|
|
|
|
*
|
|
|
|
* @param rect GeometryRect
|
|
|
|
* @returns {null|GeometryRect}
|
|
|
|
*/
|
|
|
|
getRectIntersection(rect)
|
|
|
|
{
|
2020-01-22 22:50:45 +01:00
|
|
|
let distanceToOrigin = this.getCenter().getDistanceToPoint(rect.getCenter());
|
|
|
|
|
|
|
|
if (distanceToOrigin > this.getDiagonal() * 0.5 + rect.getDiagonal() * 0.5) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2020-01-19 00:45:17 +01:00
|
|
|
let intersectionPoints = new GeometryPointCollection();
|
|
|
|
|
|
|
|
this.getRectanglePoints().forEach(
|
|
|
|
(point) => {
|
|
|
|
if (rect.isContainingPoint(point)) {
|
|
|
|
intersectionPoints.addGeometryPoint(point);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
if (intersectionPoints.getLength() >= 4) {
|
|
|
|
return intersectionPoints.getRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
rect.getRectanglePoints().forEach(
|
|
|
|
(point) => {
|
|
|
|
if (this.isContainingPoint(point)) {
|
|
|
|
intersectionPoints.addGeometryPoint(point);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
if (intersectionPoints.getLength() >= 4) {
|
|
|
|
return intersectionPoints.getRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.getBorderIntersectonsWithRect(rect).forEach(
|
|
|
|
(point) => {
|
|
|
|
intersectionPoints.addGeometryPoint(point);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
if (intersectionPoints.getLength() >= 2) {
|
|
|
|
return intersectionPoints.getRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2020-01-22 22:50:45 +01:00
|
|
|
getCenter()
|
|
|
|
{
|
|
|
|
return new GeometryPoint(
|
|
|
|
this.position.x + this.width * 0.5,
|
|
|
|
this.position.y + this.height * 0.5
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
getDiagonal()
|
|
|
|
{
|
|
|
|
return new GeometryStroke(
|
|
|
|
this.position,
|
|
|
|
new GeometryPoint(this.position.x + this.width, this.position.y + this.height)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-01-19 00:45:17 +01:00
|
|
|
/**
|
|
|
|
* Visualizes the rect.
|
|
|
|
*
|
|
|
|
* @param context Context
|
|
|
|
* @param color string
|
|
|
|
*/
|
|
|
|
draw(context, color = 'red')
|
|
|
|
{
|
|
|
|
context.fillStyle = color;
|
|
|
|
context.fillRect(this.position.x, this.position.y, this.width, this.height);
|
|
|
|
this.getBorderTop().draw(context);
|
|
|
|
this.getBorderLeft().draw(context);
|
|
|
|
this.getBorderRight().draw(context);
|
|
|
|
this.getBorderBottom().draw(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|