wrapping for pointy hexagons
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
import Cartographer from './cartographer.js';
|
||||
|
||||
import * as funky from './funky';
|
||||
import {rangeInclusive, sqrt3} from './utils.js';
|
||||
|
||||
import Hex from './hex.js';
|
||||
import Point from './point.js';
|
||||
|
||||
const tilePointToHex = ({tilePoint, pixelPoint}) => ({tilePoint: new Hex(tilePoint), pixelPoint});
|
||||
|
||||
export default class CartographerPointyXYZ extends Cartographer {
|
||||
constructor(settings) {
|
||||
constructor (settings) {
|
||||
super(settings);
|
||||
|
||||
[
|
||||
@@ -26,54 +29,56 @@ export default class CartographerPointyXYZ extends Cartographer {
|
||||
'calculateVerticalScale',
|
||||
|
||||
'tileToPixel',
|
||||
'pixelToTile',
|
||||
'_pixelToTile',
|
||||
'teleport',
|
||||
|
||||
'inBounds',
|
||||
'enforceBoundries',
|
||||
'boundingBox',
|
||||
].map(method => this[method] = this[method].bind(this));
|
||||
}
|
||||
|
||||
tileHeight() {
|
||||
tileHeight () {
|
||||
return this.maxWidth();
|
||||
}
|
||||
|
||||
tileWidth() {
|
||||
tileWidth () {
|
||||
return this.minWidth();
|
||||
}
|
||||
|
||||
maxWidth() {
|
||||
maxWidth () {
|
||||
return this.scale * 2;
|
||||
}
|
||||
|
||||
minWidth() {
|
||||
minWidth () {
|
||||
return this.scale * sqrt3;
|
||||
}
|
||||
|
||||
horizontalOverhang() {
|
||||
horizontalOverhang () {
|
||||
return 0;
|
||||
}
|
||||
|
||||
verticalOverhang() {
|
||||
verticalOverhang () {
|
||||
return this.maxWidth() * 0.25;
|
||||
}
|
||||
|
||||
horizontalDistance() {
|
||||
horizontalDistance () {
|
||||
return this.minWidth();
|
||||
}
|
||||
|
||||
verticalDistance() {
|
||||
verticalDistance () {
|
||||
return this.maxWidth() * (3/4);
|
||||
}
|
||||
|
||||
calculateHorizontalScale(pixels, tiles) {
|
||||
calculateHorizontalScale (pixels, tiles) {
|
||||
return pixels / tiles / sqrt3;
|
||||
}
|
||||
|
||||
calculateVerticalScale(pixels, tiles) {
|
||||
calculateVerticalScale (pixels, tiles) {
|
||||
return pixels / (tiles * 0.75 + 0.25) / 2;
|
||||
}
|
||||
|
||||
tileToPixel(hex) {
|
||||
tileToPixel (hex) {
|
||||
hex = hex instanceof Hex ? hex : new Hex(...arguments);
|
||||
|
||||
const pixelX = this.scale * sqrt3 * (hex.getQ() + (hex.getR() / 2));
|
||||
@@ -82,7 +87,7 @@ export default class CartographerPointyXYZ extends Cartographer {
|
||||
return new Point(pixelX + this.originX, pixelY + this.originY);
|
||||
}
|
||||
|
||||
pixelToTile(point) {
|
||||
_pixelToTile (point) {
|
||||
point = point instanceof Point ? point : new Point(...arguments);
|
||||
|
||||
const pixelX = point.getX() - this.originX;
|
||||
@@ -94,45 +99,108 @@ export default class CartographerPointyXYZ extends Cartographer {
|
||||
return new Hex(q, r);
|
||||
}
|
||||
|
||||
inBounds (q, r, s = -q - r) {
|
||||
teleport (hex) {
|
||||
hex = hex instanceof Hex ? hex : new Hex(hex);
|
||||
let {col, row} = Hex.cubeToEvenR(hex);
|
||||
|
||||
if (this.radius) {
|
||||
}
|
||||
else {
|
||||
// ensure odd-width maps wrap properly
|
||||
if (this.height % 2) {
|
||||
const offset = Math.floor(row / this.height);
|
||||
|
||||
let horizontalAdjust = offset / 2;
|
||||
horizontalAdjust = offset % 2 === 0 ? horizontalAdjust :
|
||||
row % 2 ? Math.ceil(horizontalAdjust) :
|
||||
Math.floor(horizontalAdjust);
|
||||
|
||||
col -= horizontalAdjust;
|
||||
}
|
||||
|
||||
const halfWidth = Math.floor(this.width / 2);
|
||||
const halfHeight = Math.floor(this.height / 2);
|
||||
|
||||
if (this.negativeTiles) {
|
||||
col += halfWidth;
|
||||
row += halfHeight;
|
||||
}
|
||||
|
||||
col = col % this.width;
|
||||
row = row % this.height;
|
||||
|
||||
col = col < 0 ? col + this.width : col;
|
||||
row = row < 0 ? row + this.height : row;
|
||||
|
||||
if (this.negativeTiles) {
|
||||
col -= halfWidth;
|
||||
row -= halfHeight;
|
||||
}
|
||||
|
||||
return Hex.evenRToCube(col, row);
|
||||
}
|
||||
}
|
||||
|
||||
inBounds (hex) {
|
||||
hex = hex instanceof Hex ? hex : new Hex(hex);
|
||||
|
||||
if (this.radius) {
|
||||
if (this.negativeTiles) {
|
||||
return Math.max(Math.abs(q), Math.abs(r), Math.abs(s)) <= Math.floor(this.radius);
|
||||
return Math.max(Math.abs(hex.x), Math.abs(hex.y), Math.abs(hex.z)) <= Math.floor(this.radius);
|
||||
}
|
||||
else {
|
||||
return Math.max(Math.abs(q - this.radius), Math.abs(r + this.radius), Math.abs(s)) <= this.radius;
|
||||
return Math.max(Math.abs(hex.x - this.radius), Math.abs(hex.y + this.radius), Math.abs(hex.z)) <= this.radius;
|
||||
}
|
||||
}
|
||||
else if (this.width || this.height) {
|
||||
if (this.negativeTiles) {
|
||||
return (!this.height || (Math.abs(r) < this.height / 2))
|
||||
&& (!this.width || (Math.abs(-q - Math.floor(r / 2)) < (this.width / 2)));
|
||||
return (!this.width || (Math.abs(hex.x) < this.width / 2))
|
||||
&& (!this.height || (Math.abs(-hex.y - Math.floor(hex.x / 2)) < (this.height / 2)));
|
||||
}
|
||||
else {
|
||||
return (!this.height || (r >= 0 && r < this.height))
|
||||
&& (!this.width || (q <= (Math.floor(r / 2)) && (q - Math.floor(r / 2)) < this.width));
|
||||
return (!this.width || (hex.x >= 0 && hex.x < this.width))
|
||||
&& (!this.height || (hex.y <= (Math.floor(hex.x / 2) * -1) && (-hex.y - Math.floor(hex.x / 2)) < this.height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boundingBox(upperLeftPoint, upperRightPoint, lowerLeftPoint, lowerRightPoint) {
|
||||
const upperLeftTile = this.pixelToTile(upperLeftPoint);
|
||||
const lowerLeftTile = this.pixelToTile(lowerLeftPoint);
|
||||
const lowerRightTile = this.pixelToTile(lowerRightPoint);
|
||||
const upperRightTile = this.pixelToTile(upperRightPoint);
|
||||
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 lowerLeftTile = this._pixelToTile(lowerLeftPoint);
|
||||
const lowerRightTile = this._pixelToTile(lowerRightPoint);
|
||||
const upperRightTile = this._pixelToTile(upperRightPoint);
|
||||
|
||||
const rows = rangeInclusive(upperLeftTile.getR() -1 , lowerLeftTile.getR() + 1);
|
||||
|
||||
const width = upperRightTile.getQ() - upperLeftTile.getQ();
|
||||
return rows.map((r, index) => {
|
||||
|
||||
const makeAPointPair = tilePoint => ({tilePoint, pixelPoint: this.tileToPixel(tilePoint)});
|
||||
|
||||
const processColumn = (r, index) => {
|
||||
const left = upperLeftTile.getQ() - Math.floor(index / 2);
|
||||
const right = left + width;
|
||||
const columns = rangeInclusive(left, right + 1);
|
||||
|
||||
return columns.map(q => ({q, r}))
|
||||
.reduce((flat, list) => flat.concat(list), [])
|
||||
.filter(({q, r}) => this.inBounds(q, r))
|
||||
.map(({q, r}) => new Hex(q, r));
|
||||
});
|
||||
const makeAPoint = q => Hex.qrToCube(q, r); //({x: q, z: r, y: -q - r});
|
||||
|
||||
return funky.chain(columns)
|
||||
.map(makeAPoint)
|
||||
.map(makeAPointPair)
|
||||
.map(this.enforceBoundries)
|
||||
.compact()
|
||||
.map(tilePointToHex)
|
||||
.value();
|
||||
};
|
||||
|
||||
return funky.chain(rows)
|
||||
.map(processColumn)
|
||||
.flatten()
|
||||
.value();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user