com.voxelplugineering.voxelsniper.brush.effect.morphological.LinearBlendMaterialOperation.java Source code

Java tutorial

Introduction

Here is the source code for com.voxelplugineering.voxelsniper.brush.effect.morphological.LinearBlendMaterialOperation.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 The Voxel Plugineering Team
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.voxelplugineering.voxelsniper.brush.effect.morphological;

import java.util.Map;

import com.google.common.base.Optional;
import com.google.common.collect.Maps;
import com.voxelplugineering.voxelsniper.util.math.Maths;
import com.voxelplugineering.voxelsniper.world.World;
import com.voxelplugineering.voxelsniper.world.material.Material;

public class LinearBlendMaterialOperation implements FilterOperation {
    private int count;
    private double maxDistance;

    private Map<Material, Double> mats;

    public LinearBlendMaterialOperation() {
        this.reset();
    }

    @Override
    public String getName() {
        return "blend";
    }

    @Override
    public boolean checkPosition(int x, int y, int z, int dx, int dy, int dz, World w, Material m) {
        if (!(dx == 0 && dy == 0 && dz == 0)) {
            // TODO: Use world bounds instead of hardcoded magical values from
            // Minecraft.
            int clampedY = Maths.clamp(y + dy, 0, 255);
            Material mat = w.getBlock(x + dx, clampedY, z + dz).get().getMaterial();
            if (mats.containsKey(mat)) {
                mats.put(mat, mats.get(mat) + Math.sqrt(dx * dx + dy * dy + dz * dz));
            } else {
                mats.put(mat, Math.sqrt(dx * dx + dy * dy + dz * dz));
            }
            count++;
            maxDistance = (Math.sqrt(dx * dx + dy * dy + dz * dz) > maxDistance)
                    ? Math.sqrt(dx * dx + dy * dy + dz * dz)
                    : maxDistance;
        }
        return false;
    }

    @Override
    public Optional<Material> getResult() {
        // Select the material which occurred the most.
        double n = 0;
        Material winner = null;
        for (Map.Entry<Material, Double> e : mats.entrySet()) {
            if (count * maxDistance - e.getValue() > n) {
                winner = e.getKey();
                n = e.getValue();
            }
        }

        // If multiple materials occurred the most, the tie check will become
        // true.
        boolean tie = false;
        for (Map.Entry<Material, Double> e : mats.entrySet()) {
            if (e.getValue() == n && !e.getKey().equals(winner)) {
                tie = true;
            }
        }

        // If a tie is found, no change is made.
        if (!tie) {
            return Optional.of(winner);
        }
        return Optional.of(null);
    }

    @Override
    public void reset() {
        Map<Material, Integer> mats = Maps.newHashMapWithExpectedSize(10);
        count = 0;
        maxDistance = 0;
    }
}