wrapping for pointy hexagons
This commit is contained in:
@@ -253,7 +253,7 @@ export default class CartographerFlatXYZ extends Cartographer {
|
|||||||
|
|
||||||
teleport (hex) {
|
teleport (hex) {
|
||||||
hex = hex instanceof Hex ? hex : new Hex(hex);
|
hex = hex instanceof Hex ? hex : new Hex(hex);
|
||||||
let {col, row} = hex.getOffsetHex();
|
let {col, row} = Hex.cubeToEvenQ(hex);
|
||||||
|
|
||||||
if (this.radius) {
|
if (this.radius) {
|
||||||
}
|
}
|
||||||
@@ -289,11 +289,11 @@ export default class CartographerFlatXYZ extends Cartographer {
|
|||||||
row -= halfHeight;
|
row -= halfHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Hex.offsetToCube(col, row);
|
return Hex.evenQToCube(col, row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inBounds ({x, y, z = -x - y}) {
|
inBounds ({x, z, y = -x - z}) {
|
||||||
if (this.radius) {
|
if (this.radius) {
|
||||||
if (this.negativeTiles) {
|
if (this.negativeTiles) {
|
||||||
return Math.max(Math.abs(x), Math.abs(y), Math.abs(z)) <= Math.floor(this.radius);
|
return Math.max(Math.abs(x), Math.abs(y), Math.abs(z)) <= Math.floor(this.radius);
|
||||||
@@ -337,7 +337,7 @@ export default class CartographerFlatXYZ extends Cartographer {
|
|||||||
const bottom = top + height;
|
const bottom = top + height;
|
||||||
const rows = rangeInclusive(top, bottom + 1);
|
const rows = rangeInclusive(top, bottom + 1);
|
||||||
|
|
||||||
const makeAPoint = r => ({x: q, z: r, y: -q - r});
|
const makeAPoint = r => Hex.qrToCube(q, r);
|
||||||
|
|
||||||
return funky.chain(rows)
|
return funky.chain(rows)
|
||||||
.map(makeAPoint)
|
.map(makeAPoint)
|
||||||
@@ -348,21 +348,6 @@ export default class CartographerFlatXYZ extends Cartographer {
|
|||||||
.value();
|
.value();
|
||||||
};
|
};
|
||||||
|
|
||||||
// if (debugged < 1) {
|
|
||||||
//
|
|
||||||
// [positive3x3, positiveEast3x3, positiveMiddleEast3x3, positiveFarEast3x3].forEach(set => {
|
|
||||||
// set.forEach((input, index) => {
|
|
||||||
// const result = this.teleport(input, true);
|
|
||||||
//
|
|
||||||
// if (result.x === positive3x3[index].x && result.y === positive3x3[index].y && result.z === positive3x3[index].z) console.log(input, '->', positive3x3[index]);
|
|
||||||
// else console.log(input, '><', positive3x3[index], result);
|
|
||||||
// console.log('---------------------------------------------------');
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-');
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
return funky.chain(columns)
|
return funky.chain(columns)
|
||||||
.map(processRow)
|
.map(processRow)
|
||||||
.flatten()
|
.flatten()
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import Cartographer from './cartographer.js';
|
import Cartographer from './cartographer.js';
|
||||||
|
|
||||||
|
import * as funky from './funky';
|
||||||
import {rangeInclusive, sqrt3} from './utils.js';
|
import {rangeInclusive, sqrt3} from './utils.js';
|
||||||
|
|
||||||
import Hex from './hex.js';
|
import Hex from './hex.js';
|
||||||
import Point from './point.js';
|
import Point from './point.js';
|
||||||
|
|
||||||
|
const tilePointToHex = ({tilePoint, pixelPoint}) => ({tilePoint: new Hex(tilePoint), pixelPoint});
|
||||||
|
|
||||||
export default class CartographerPointyXYZ extends Cartographer {
|
export default class CartographerPointyXYZ extends Cartographer {
|
||||||
constructor (settings) {
|
constructor (settings) {
|
||||||
super(settings);
|
super(settings);
|
||||||
@@ -26,9 +29,11 @@ export default class CartographerPointyXYZ extends Cartographer {
|
|||||||
'calculateVerticalScale',
|
'calculateVerticalScale',
|
||||||
|
|
||||||
'tileToPixel',
|
'tileToPixel',
|
||||||
'pixelToTile',
|
'_pixelToTile',
|
||||||
|
'teleport',
|
||||||
|
|
||||||
'inBounds',
|
'inBounds',
|
||||||
|
'enforceBoundries',
|
||||||
'boundingBox',
|
'boundingBox',
|
||||||
].map(method => this[method] = this[method].bind(this));
|
].map(method => this[method] = this[method].bind(this));
|
||||||
}
|
}
|
||||||
@@ -82,7 +87,7 @@ export default class CartographerPointyXYZ extends Cartographer {
|
|||||||
return new Point(pixelX + this.originX, pixelY + this.originY);
|
return new Point(pixelX + this.originX, pixelY + this.originY);
|
||||||
}
|
}
|
||||||
|
|
||||||
pixelToTile(point) {
|
_pixelToTile (point) {
|
||||||
point = point instanceof Point ? point : new Point(...arguments);
|
point = point instanceof Point ? point : new Point(...arguments);
|
||||||
|
|
||||||
const pixelX = point.getX() - this.originX;
|
const pixelX = point.getX() - this.originX;
|
||||||
@@ -94,45 +99,108 @@ export default class CartographerPointyXYZ extends Cartographer {
|
|||||||
return new Hex(q, r);
|
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) {
|
if (this.radius) {
|
||||||
if (this.negativeTiles) {
|
|
||||||
return Math.max(Math.abs(q), Math.abs(r), Math.abs(s)) <= Math.floor(this.radius);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Math.max(Math.abs(q - this.radius), Math.abs(r + this.radius), Math.abs(s)) <= this.radius;
|
// 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(hex.x), Math.abs(hex.y), Math.abs(hex.z)) <= Math.floor(this.radius);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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) {
|
else if (this.width || this.height) {
|
||||||
if (this.negativeTiles) {
|
if (this.negativeTiles) {
|
||||||
return (!this.height || (Math.abs(r) < this.height / 2))
|
return (!this.width || (Math.abs(hex.x) < this.width / 2))
|
||||||
&& (!this.width || (Math.abs(-q - Math.floor(r / 2)) < (this.width / 2)));
|
&& (!this.height || (Math.abs(-hex.y - Math.floor(hex.x / 2)) < (this.height / 2)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return (!this.height || (r >= 0 && r < this.height))
|
return (!this.width || (hex.x >= 0 && hex.x < this.width))
|
||||||
&& (!this.width || (q <= (Math.floor(r / 2)) && (q - Math.floor(r / 2)) < this.width));
|
&& (!this.height || (hex.y <= (Math.floor(hex.x / 2) * -1) && (-hex.y - Math.floor(hex.x / 2)) < this.height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enforceBoundries ({tilePoint, pixelPoint}) {
|
||||||
|
return this.wrap ? ({tilePoint: this.teleport(tilePoint), pixelPoint}) :
|
||||||
|
this.inBounds(tilePoint) ? ({tilePoint, pixelPoint}) :
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
|
||||||
boundingBox (upperLeftPoint, upperRightPoint, lowerLeftPoint, lowerRightPoint) {
|
boundingBox (upperLeftPoint, upperRightPoint, lowerLeftPoint, lowerRightPoint) {
|
||||||
const upperLeftTile = this.pixelToTile(upperLeftPoint);
|
const upperLeftTile = this._pixelToTile(upperLeftPoint);
|
||||||
const lowerLeftTile = this.pixelToTile(lowerLeftPoint);
|
const lowerLeftTile = this._pixelToTile(lowerLeftPoint);
|
||||||
const lowerRightTile = this.pixelToTile(lowerRightPoint);
|
const lowerRightTile = this._pixelToTile(lowerRightPoint);
|
||||||
const upperRightTile = this.pixelToTile(upperRightPoint);
|
const upperRightTile = this._pixelToTile(upperRightPoint);
|
||||||
|
|
||||||
const rows = rangeInclusive(upperLeftTile.getR() -1 , lowerLeftTile.getR() + 1);
|
const rows = rangeInclusive(upperLeftTile.getR() -1 , lowerLeftTile.getR() + 1);
|
||||||
|
|
||||||
const width = upperRightTile.getQ() - upperLeftTile.getQ();
|
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 left = upperLeftTile.getQ() - Math.floor(index / 2);
|
||||||
const right = left + width;
|
const right = left + width;
|
||||||
const columns = rangeInclusive(left, right + 1);
|
const columns = rangeInclusive(left, right + 1);
|
||||||
|
|
||||||
return columns.map(q => ({q, r}))
|
const makeAPoint = q => Hex.qrToCube(q, r); //({x: q, z: r, y: -q - r});
|
||||||
.reduce((flat, list) => flat.concat(list), [])
|
|
||||||
.filter(({q, r}) => this.inBounds(q, r))
|
return funky.chain(columns)
|
||||||
.map(({q, r}) => new Hex(q, r));
|
.map(makeAPoint)
|
||||||
});
|
.map(makeAPointPair)
|
||||||
|
.map(this.enforceBoundries)
|
||||||
|
.compact()
|
||||||
|
.map(tilePointToHex)
|
||||||
|
.value();
|
||||||
|
};
|
||||||
|
|
||||||
|
return funky.chain(rows)
|
||||||
|
.map(processColumn)
|
||||||
|
.flatten()
|
||||||
|
.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
39
src/hex.js
39
src/hex.js
@@ -35,7 +35,37 @@ function roundOff(hex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class Hex extends Point {
|
export default class Hex extends Point {
|
||||||
static offsetToCube (col, row) {
|
static qrToCube (q, r) {
|
||||||
|
return {
|
||||||
|
x: q,
|
||||||
|
y: computeY(q, r),
|
||||||
|
z: r,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static cubeToEvenR ({x, y, z}) {
|
||||||
|
const col = x + (z + (z & 1)) / 2;;
|
||||||
|
const row = z;
|
||||||
|
|
||||||
|
return {col, row};
|
||||||
|
}
|
||||||
|
|
||||||
|
static evenRToCube (col, row) {
|
||||||
|
const x = col - (row + (row & 1)) / 2;;
|
||||||
|
const z = row;
|
||||||
|
const y = -x - z;
|
||||||
|
|
||||||
|
return new Hex(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cubeToEvenQ ({x, y, z}) {
|
||||||
|
const col = x;
|
||||||
|
const row = z + (x + (x & 1)) / 2;
|
||||||
|
|
||||||
|
return {col, row};
|
||||||
|
}
|
||||||
|
|
||||||
|
static evenQToCube (col, row) {
|
||||||
const x = col;
|
const x = col;
|
||||||
const z = row - (col + (col & 1)) / 2;
|
const z = row - (col + (col & 1)) / 2;
|
||||||
const y = -x - z;
|
const y = -x - z;
|
||||||
@@ -137,11 +167,4 @@ export default class Hex extends Point {
|
|||||||
this.y = computeY(this.x, this.z);
|
this.y = computeY(this.x, this.z);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
getOffsetHex () {
|
|
||||||
const col = this.x;
|
|
||||||
const row = this.z + (this.x + (this.x & 1)) / 2;
|
|
||||||
|
|
||||||
return {col, row};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user