Files
Tessellate/src/cartographerFlatXY.js
2018-12-28 16:31:55 -05:00

150 lines
3.2 KiB
JavaScript

import Cartographer from './cartographer.js';
import * as funky from './funky';
import {rangeInclusive, invSqrt2} from './utils.js';
import Point from './point.js';
import Square from './square.js';
const tilePointToSquare = ({tilePoint, pixelPoint}) => ({tilePoint: new Square(tilePoint), pixelPoint});
export default class CartographerFlatXY extends Cartographer {
constructor(settings) {
super(settings);
[
'tileHeight',
'tileWidth',
'maxWidth',
'minWidth',
'horizontalOverhang',
'verticalOverhang',
'horizontalDistance',
'verticalDistance',
'calculateHorizontalScale',
'calculateVerticalScale',
'tileToPixel',
'_pixelToTile',
'teleport',
'inBounds',
'enforceBoundries',
'boundingBox',
].map(method => this[method] = this[method].bind(this));
}
tileHeight() {
return this.minWidth();
}
tileWidth() {
return this.minWidth();
}
maxWidth() {
return this.scale * 2;
}
minWidth() {
return this.maxWidth() * invSqrt2;
}
horizontalOverhang() {
return 0;
}
verticalOverhang() {
return 0;
}
horizontalDistance() {
return this.minWidth();
}
verticalDistance() {
return this.minWidth();
}
calculateHorizontalScale(pixels, tiles) {
return pixels / tiles / invSqrt2 / 2;
}
calculateVerticalScale(pixels, tiles) {
return pixels / tiles / invSqrt2 / 2;
}
tileToPixel(square) {
square = square instanceof Square ? square : new Square(...arguments);
const x = square.getX() * this.minWidth();
const y = square.getY() * this.minWidth();
return new Point(x + this.originX, this.originY - y);
}
_pixelToTile (point) {
point = point instanceof Point ? point : new Point(...arguments);
const pixelX = point.getX() - this.originX;
const pixelY = this.originY - point.getY();
const x = pixelX / this.minWidth();
const y = pixelY / this.minWidth();
return new Square(x, y);
}
teleport ({x, y}) {
x = x % this.width;
y = y % this.height;
x = x < 0 ? this.width + x : x;
y = y < 0 ? this.height + y : y;
return new Point(x, y);
}
inBounds ({x, y}) {
if (this.negativeTiles) {
return (!this.width || Math.abs(x) <= Math.floor(this.width / 2))
&& (!this.height || Math.abs(y) <= Math.floor(this.height / 2));
}
else {
return (!this.width || (x >= 0 && x < this.width))
&& (!this.height || (y >= 0 && y < this.height));
}
}
enforceBoundries ({tilePoint, pixelPoint}) {
return this.wrap ? ({tilePoint: this.teleport(tilePoint), pixelPoint}) :
this.inBounds(tilePoint) ? ({tilePoint, pixelPoint}) :
null;
}
boundingBox(upperLeftPoint, upperRightPoint, lowerLeftPoint, lowerRightPoint) {
const upperLeftTile = this._pixelToTile(upperLeftPoint);
const lowerRightTile = this._pixelToTile(lowerRightPoint);
const upperRightTile = this._pixelToTile(upperRightPoint);
const columns = rangeInclusive(upperLeftTile.getX(), upperRightTile.getX());
const rows = rangeInclusive(lowerRightTile.getY(), upperLeftTile.getY());
const makeAPoint = x => rows.map(y => ({x, y}));
const makeAPointPair = tilePoint => ({tilePoint, pixelPoint: this.tileToPixel(tilePoint)});
return funky.chain(columns)
.map(makeAPoint)
.flatten()
.map(makeAPointPair)
.map(this.enforceBoundries)
.compact()
.map(tilePointToSquare)
.value();
}
}