classpublicPriority 3
PixelDistanceProvider
com.hypixel.hytale.server.worldgen.zoom.PixelDistanceProvider
5
Methods
5
Public Methods
7
Fields
1
Constructors
Constants
intTABLE_SIZE= 8
Constructors
public
PixelDistanceProvider(PixelProvider image)Methods
Public Methods (5)
public
boolean contains(int pixel)@Override
public
double distanceSqToDifferentPixel(double ox, double oy, int px, int py)public
IntSet getColors()@Nonnull
public
int size()@Override
public
String toString()@Nonnull@Override
Fields
Protected Fields (7)
protected
int cellsXprotected
int cellsYprotected
int heightprotected
PixelProvider imageprotected
IntSet pixelsprotected
PixelDistanceProvider.IPixelSet[] tableprotected
int widthSource Code
package com.hypixel.hytale.server.worldgen.zoom;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import javax.annotation.Nonnull;
public class PixelDistanceProvider {
private static final int TABLE_SIZE = 8;
@Nonnull
protected final PixelProvider image;
protected final int width;
protected final int height;
protected final int cellsX;
protected final int cellsY;
@Nonnull
protected final PixelDistanceProvider.IPixelSet[] table;
@Nonnull
protected final IntSet pixels;
public PixelDistanceProvider(@Nonnull PixelProvider image) {
this.image = image;
this.width = image.getWidth();
this.height = image.getHeight();
this.cellsX = image.getWidth() / 8;
this.cellsY = image.getHeight() / 8;
this.table = new PixelDistanceProvider.IPixelSet[this.cellsX * this.cellsY];
this.pixels = new IntOpenHashSet();
this.prepareSegmentTable();
}
@Nonnull
public IntSet getColors() {
return this.pixels;
}
public double distanceSqToDifferentPixel(double ox, double oy, int px, int py) {
px = this.clampX(px);
py = this.clampY(py);
int color = this.image.getPixel(px, py);
int cellX = px / 8;
int cellY = py / 8;
double distance = 1.0 / 0.0;
int minX = Math.max(cellX - 1, 0);
int maxX = Math.min(cellX + 2, this.cellsX);
int minY = Math.max(cellY - 1, 0);
int maxY = Math.min(cellY + 2, this.cellsY);
for (int ix = minX; ix < maxX; ix++) {
for (int iy = minY; iy < maxY; iy++) {
double dist = this.distanceSqToDiffInSeq(ox, oy, color, ix, iy);
if (dist < distance) {
distance = dist;
}
}
}
return distance;
}
protected double distanceSqToDiffInSeq(double ox, double oy, int pixel, int cellX, int cellY) {
double distSq = 1.0 / 0.0;
if (this.hasDifferentPixel(cellX, cellY, pixel)) {
int offsetX = cellX * 8;
int offsetY = cellY * 8;
for (int ix = 0; ix < 8; ix++) {
int px = ix + offsetX;
for (int iy = 0; iy < 8; iy++) {
int py = iy + offsetY;
if (pixel != this.image.getPixel(px, py)) {
double dist = distanceSqToPixel(ox, oy, px, py);
if (dist < distSq) {
distSq = dist;
}
}
}
}
}
return distSq;
}
protected boolean hasDifferentPixel(int cellX, int cellY, int pixel) {
PixelDistanceProvider.IPixelSet pixelSet = this.table[this.cellIndex(cellX, cellY)];
return !pixelSet.contains(pixel) || pixelSet.size() > 1;
}
private void prepareSegmentTable() {
for (int cellX = 0; cellX < this.cellsX; cellX++) {
for (int cellY = 0; cellY < this.cellsY; cellY++) {
IntSet colors = new IntOpenHashSet();
int offsetX = cellX * 8;
int offsetY = cellY * 8;
for (int ix = 0; ix < 8; ix++) {
for (int iy = 0; iy < 8; iy++) {
int x = ix + offsetX;
int y = iy + offsetY;
if (x < this.width && y < this.height) {
colors.add(this.image.getPixel(x, y));
}
}
}
this.pixels.addAll(colors);
if (colors.size() == 1) {
this.table[this.cellIndex(cellX, cellY)] = new PixelDistanceProvider.SinglePixelSet(colors.iterator().nextInt());
} else {
this.table[this.cellIndex(cellX, cellY)] = new PixelDistanceProvider.MultiplePixelSet(colors);
}
}
}
}
protected int clampX(int x) {
if (x < 0) {
return 0;
} else {
return x >= this.width ? this.width - 1 : x;
}
}
protected int clampY(int y) {
if (y < 0) {
return 0;
} else {
return y >= this.height ? this.height - 1 : y;
}
}
protected int cellIndex(int cellX, int cellY) {
return cellX * this.cellsY + cellY;
}
private static double distanceSqToPixel(double ox, double oy, int px, int py) {
double dx = Math.max(Math.max((double)px - ox, ox - (double)px - 1.0), 0.0);
double dy = Math.max(Math.max((double)py - oy, oy - (double)py - 1.0), 0.0);
return dx * dx + dy * dy;
}
private interface IPixelSet {
boolean contains(int var1);
int size();
}
private static class MultiplePixelSet implements PixelDistanceProvider.IPixelSet {
private final IntSet pixels;
MultiplePixelSet(IntSet pixels) {
this.pixels = pixels;
}
@Override
public boolean contains(int pixel) {
return this.pixels.contains(pixel);
}
@Override
public int size() {
return this.pixels.size();
}
@Nonnull
@Override
public String toString() {
return "MultiplePixelSet{pixels=" + this.pixels + "}";
}
}
private static class SinglePixelSet implements PixelDistanceProvider.IPixelSet {
private final int pixel;
SinglePixelSet(int pixel) {
this.pixel = pixel;
}
@Override
public boolean contains(int pixel) {
return this.pixel == pixel;
}
@Override
public int size() {
return 1;
}
@Nonnull
@Override
public String toString() {
return "SinglePixelSet{pixel=" + this.pixel + "}";
}
}
}