Package com.sk89q.worldedit.math.interpolation

Source Code of com.sk89q.worldedit.math.interpolation.LinearInterpolation

/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

// $Id$

package com.sk89q.worldedit.math.interpolation;

import com.sk89q.worldedit.Vector;

import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;

/**
* Simple linear interpolation. Mainly used for testing.
*/
public class LinearInterpolation implements Interpolation {

    private List<Node> nodes;

    @Override
    public void setNodes(List<Node> nodes) {
        checkNotNull(nodes);
       
        this.nodes = nodes;
    }

    @Override
    public Vector getPosition(double position) {
        if (nodes == null)
            throw new IllegalStateException("Must call setNodes first.");

        if (position > 1)
            return null;

        position *= nodes.size() - 1;

        final int index1 = (int) Math.floor(position);
        final double remainder = position - index1;

        final Vector position1 = nodes.get(index1).getPosition();
        final Vector position2 = nodes.get(index1 + 1).getPosition();

        return position1.multiply(1.0 - remainder).add(position2.multiply(remainder));
    }

    /*
    Formula for position:
        p1*(1-t) + p2*t
    Formula for position in Horner/monomial form:
        (p2-p1)*t + p1
    1st Derivative:
        p2-p1
    2nd Derivative:
        0
    Integral:
        (p2-p1)/2*t^2 + p1*t + constant
    Integral in Horner form:
        ((p2-p1)/2*t + p1)*t + constant
    */

    @Override
    public Vector get1stDerivative(double position) {
        if (nodes == null)
            throw new IllegalStateException("Must call setNodes first.");

        if (position > 1)
            return null;

        position *= nodes.size() - 1;

        final int index1 = (int) Math.floor(position);

        final Vector position1 = nodes.get(index1).getPosition();
        final Vector position2 = nodes.get(index1 + 1).getPosition();

        return position2.subtract(position1);
    }

    @Override
    public double arcLength(double positionA, double positionB) {
        if (nodes == null)
            throw new IllegalStateException("Must call setNodes first.");

        if (positionA > positionB)
            return arcLength(positionB, positionA);

        positionA *= nodes.size() - 1;
        positionB *= nodes.size() - 1;

        final int indexA = (int) Math.floor(positionA);
        final double remainderA = positionA - indexA;

        final int indexB = (int) Math.floor(positionB);
        final double remainderB = positionB - indexB;

        return arcLengthRecursive(indexA, remainderA, indexB, remainderB);
    }

    /**
     * Assumes a < b.
     */
    private double arcLengthRecursive(int indexA, double remainderA, int indexB, double remainderB) {
        switch (indexB - indexA) {
        case 0:
            return arcLengthRecursive(indexA, remainderA, remainderB);

        case 1:
            // This case is merely a speed-up for a very common case
            return
                    arcLengthRecursive(indexA, remainderA, 1.0) +
                    arcLengthRecursive(indexB, 0.0, remainderB);

        default:
            return
                    arcLengthRecursive(indexA, remainderA, indexB - 1, 1.0) +
                    arcLengthRecursive(indexB, 0.0, remainderB);
        }
    }

    private double arcLengthRecursive(int index, double remainderA, double remainderB) {
        final Vector position1 = nodes.get(index).getPosition();
        final Vector position2 = nodes.get(index + 1).getPosition();

        return position1.distance(position2) * (remainderB - remainderA);
    }

    @Override
    public int getSegment(double position) {
        if (nodes == null)
            throw new IllegalStateException("Must call setNodes first.");

        if (position > 1)
            return Integer.MAX_VALUE;

        position *= nodes.size() - 1;

        return (int) Math.floor(position);
    }

}
TOP

Related Classes of com.sk89q.worldedit.math.interpolation.LinearInterpolation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.