All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.enterprisemath.math.fa.StraightLineSegmentFunction Maven / Gradle / Ivy

The newest version!
package com.enterprisemath.math.fa;

import com.enterprisemath.math.algebra.Vector;
import com.enterprisemath.utils.DomainUtils;
import com.enterprisemath.utils.ValidationUtils;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.lang3.builder.ToStringBuilder;

/**
 * Real to real function which is created by straight line segments.
 * These segments are interpolated / extrapolated between the defined points.
 * Extrapolation is linear using two first / last points.
 *
 * @author radek.hecl
 */
public class StraightLineSegmentFunction implements Function {

    /**
     * Builder object.
     */
    public static class Builder {

        /**
         * Pivot points.
         */
        private SortedMap pivotPoints = new TreeMap();

        /**
         * Sets pivot points.
         *
         * @param pivotPoints pivot points
         * @return this instance
         */
        public Builder setPivotPoints(SortedMap pivotPoints) {
            this.pivotPoints = DomainUtils.softCopySortedMap(pivotPoints);
            return this;
        }

        /**
         * Adds pivot point.
         *
         * @param x value x
         * @param y value y
         * @return this instance
         */
        public Builder addPivotPoint(double x, double y) {
            this.pivotPoints.put(x, y);
            return this;
        }

        /**
         * Builds the result object.
         *
         * @return created object
         */
        public StraightLineSegmentFunction build() {
            return new StraightLineSegmentFunction(this);
        }
    }

    /**
     * Pivot points.
     */
    private SortedMap pivotPoints;

    /**
     * List of pivot points in the x axis.
     */
    private List pivotXList;

    /**
     * Creates new instance.
     *
     * @param builder builder object
     */
    public StraightLineSegmentFunction(Builder builder) {
        this.pivotPoints = DomainUtils.softCopyUnmodifiableSortedMap(builder.pivotPoints);
        guardInvariants();
        pivotXList = DomainUtils.softCopyUnmodifiableList(pivotPoints.keySet());
    }

    /**
     * Guards this object to be consistent. Throws exception if this is not the case.
     */
    private void guardInvariants() {
        ValidationUtils.guardNotNullMap(pivotPoints, "pivot points cannot contain null");
        ValidationUtils.guardTrue(pivotPoints.size() >= 2, "at least 2 pivot points are required");
    }

    @Override
    public Double getValue(Double x) {
        if (pivotPoints.containsKey(x)) {
            return pivotPoints.get(x);
        }
        double x1 = 0;
        double x2 = 0;
        if (x < pivotXList.get(0)) {
            x1 = pivotXList.get(0);
            x2 = pivotXList.get(1);
        }
        else if (x > pivotXList.get(pivotXList.size() - 1)) {
            x1 = pivotXList.get(pivotXList.size() - 2);
            x2 = pivotXList.get(pivotXList.size() - 1);
        }
        else {
            for (double px : pivotXList) {
                if (px < x) {
                    x1 = px;
                }
                else {
                    x2 = px;
                    break;
                }
            }
        }
        double t = (x - x1) / (x2 - x1);
        return (1 - t) * pivotPoints.get(x1) + t * pivotPoints.get(x2);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    /**
     * Creates new instance.
     *
     * @param p1 first pivot point
     * @param p2 second pivot point
     * @param others other pivot points
     * @return created instance
     */
    public static StraightLineSegmentFunction create(Vector p1, Vector p2, Vector... others) {
        StraightLineSegmentFunction.Builder res = new StraightLineSegmentFunction.Builder();
        ValidationUtils.guardEquals(2, p1.getDimension(), "dimension of all pivot points must be 2");
        res.addPivotPoint(p1.getComponent(0), p1.getComponent(1));
        ValidationUtils.guardEquals(2, p2.getDimension(), "dimension of all pivot points must be 2");
        res.addPivotPoint(p2.getComponent(0), p2.getComponent(1));
        if (others != null) {
            for (Vector p : others) {
                ValidationUtils.guardEquals(2, p.getDimension(), "dimension of all pivot points must be 2");
                res.addPivotPoint(p.getComponent(0), p.getComponent(1));
            }
        }
        return res.build();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy