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

de.tsl2.nano.math.vector.Vector Maven / Gradle / Ivy

/*
 * File: $HeadURL$
 * Id  : $Id$
 * 
 * created by: ts
 * created on: 05.01.2012
 * 
 * Copyright: (c) Thomas Schneider 2012, all rights reserved
 */
package de.tsl2.nano.math.vector;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;

import de.tsl2.nano.collection.FloatArray;
import de.tsl2.nano.core.ManagedException;
import de.tsl2.nano.core.util.ByteUtil;
import de.tsl2.nano.core.util.FileUtil;

/**
 * Simple-handling numeric n-dim vector with common calculations. See {@link Coordinate} for further informations.
 * 
 * @author ts
 * 
 */
public class Vector extends Coordinate implements Comparable {

    /** serialVersionUID */
    private static final long serialVersionUID = -2179340122151337364L;

    /**
     * @param v any vector
     */
    public Vector(float... v) {
        super(v);
    }

    /**
     * create
     * 
     * @param dim dimension
     * @param defaultValue default value for each cell
     * @return new vector
     */
    public static Vector create(int dim, float defaultValue) {
        float v[] = new float[dim];
        for (int i = 0; i < v.length; i++) {
            v[i] = defaultValue;
        }
        return new Vector(v);
    }

    /**
     * scale
     * 
     * @param v vector to be scaled
     * @param f scale factor
     * @return new vector instance, scaled by f.
     */
    public static Vector scale(Vector v, float f) {
        v = v.clone(1);
        v.scale(f);
        return v;
    }

    /**
     * add
     * 
     * @param v vector to add
     */
    public void add(Vector v) {
        add(v.x);
    }

    /**
     * add
     * 
     * @param v1 source vector to add the vectors vv to.
     * @param vv adding vectors
     * @return new vector instance as sum of all vectors
     */
    public static Vector add(Vector v1, Vector... vv) {
        Vector v = v1.clone(1);
        for (int i = 0; i < vv.length; i++) {
            v.add(vv[i]);
        }
        return v;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void add(float... v) {
        checkDimension(v);
        for (int i = 0; i < v.length; i++) {
            this.x[i] += v[i];
        }
    }

    /**
     * subtract
     * 
     * @param v1 source vector to subtract the vectors vv from.
     * @param vv subtractions vectors
     * @return new vector instance as subtraction
     */
    public static Vector subtract(Vector v1, Vector... vv) {
        Vector v = v1.clone(1);
        for (int i = 0; i < vv.length; i++) {
            v.subtract(vv[i]);
        }
        return v;
    }

    /**
     * subtract
     * 
     * @param v vector to subtract
     */
    protected void subtract(float... v) {
        checkDimension(v);
        for (int i = 0; i < v.length; i++) {
            this.x[i] -= v[i];
        }
    }

    /**
     * subtract
     * 
     * @param v vector to subtract
     */
    public void subtract(Vector v) {
        subtract(v.x);
    }

//    public void crossProduct(float... v) {
//        checkDimension(v);
//        for (int i = 0; i < x.length; i++) {
//            x[i] = indexCrossProduct(i, v);
//        }
//    }
//
//    private static final float indexCrossProduct(float x, float... v) {
//        float r = 0;
//        for (int j = 0; j < v.length; j++) {
//            r += x * v[j];
//        }
//        return r;
//    }

    /**
     * see {@link #scalar(float...)}
     */
    public float scalar(Vector v) {
        return scalar(v.x);
    }

    /**
     * scalar / inner / dot product
     * 
     * @param v second operand of scalar
     * @return scalar product of this and v
     */
    protected float scalar(float... v) {
        checkDimension(v);
        float result = 0;
        for (int i = 0; i < v.length; i++) {
            result += x[i] * v[i];
        }
        return result;
    }

    /**
     * delegates to {@link #scalar(float...)}
     */
    public float multiply(Vector v) {
        return scalar(v.x);
    }

    /**
     * through the scalar product it is possible to calculate the angle between two vectors.
     * 
     * @param v another vector to calc the inner angle to
     * @return inner angle between the two vectors
     */
    public float angle(Vector v) {
        float sp = scalar(v);
        float cos = sp / (len() * v.len());
        return (float) Math.acos(cos);
    }

    /**
     * multiply with an equal-dim matrix
     * 
     * @param m matrix
     */
    public void multiply(float[]... m) {
        // do only a simple check on first vector
        checkDimension(m[0]);
        float[] n = new float[x.length];
        for (int i = 0; i < m.length; i++) {
            for (int j = 0; j < m[i].length; j++) {
                // error on indexes!
                n[i] += x[i] * m[i][j];
            }
        }
        System.arraycopy(n, 0, x, 0, x.length);
    }

    /**
     * multiply with an equal-dim matrix
     * 
     * @param m matrix
     */
    public void multiply(Vector[] m) {
        int dim = m[0].dimension();
        float[] mf = new float[dim];
        for (int i = 0; i < mf.length; i++) {
            System.arraycopy(m[i].x, 0, mf, 0, dim);
        }
        scalar(mf);
    }

    /**
     * length of current vector
     * 
     * @return
     */
    public float len() {
        float l = 0;
        for (int i = 0; i < x.length; i++) {
            l += x[i] * x[i];
        }
        return (float) Math.sqrt(l);
    }

    /**
     * distance between this and v2. see {@link #subtract(Vector, Vector...)}.
     * 
     * @param v2 second operand
     * @return distance between the two vectors
     */
    public Vector distance(Vector v2) {
        return Vector.subtract(this, v2);
    }

    /**
     * distance as scalar.
     * 
     * @param v second operand
     * @return scalar distance
     */
    public float distance(float... v) {
        checkDimension(v);
        float d = 0;
        float id;
        for (int i = 0; i < x.length; i++) {
            id = x[i] - v[i];
            d += id * id;
        }
        return (float) Math.sqrt(d);
    }

    /**
     * normalize the given vector
     * 
     * @param v vector to normalize
     * @return new normalized vector instance
     */
    public static Vector normalize(Vector v) {
        v = v.clone(1);
        v.normalize();
        return v;
    }

    /**
     * normalize vector
     */
    public void normalize() {
        float l = len();
        if (l == 0) {
            return;
        }
        for (int i = 0; i < x.length; i++) {
            x[i] /= l;
        }
    }

    /**
     * orthogonizeInPlaneWith
     * 
     * @param v2 second operand in plane with current vector.
     */
    public void orthogonizeInPlaneWith(Vector v2) {
        int a = isEVector(this);
        if (a != -1) {
            for (int i = 0; i < x.length; i++) {
                if (i == a) {
                    continue;
                }
                Vector v1 = e(x.length, i);
                if (v1.scalar(v2.x) != 0) {
                    x = v1.x;
                    break;
                }
            }
        } else {
            for (int i = 0; i < x.length; i++) {
                if (x[i] == 0) {
                    continue;
                }
                Vector v1 = clone(1);
                v1.x[i] = -v1.x[i];
                if (v1.scalar(v2.x) != 0) {
                    x = v1.x;
                    break;
                }
            }
        }
    }

    /**
     * isEVector
     * 
     * @return axis/row of 1
     */
    protected static int isEVector(Vector v) {
        if (v.len() != 1) {
            return -1;
        }
        int u = 0;
        int a = -1;
        for (int i = 0; i < v.x.length; i++) {
            if (v.x[i] == 1) {
                a = i;
                u++;
            }
        }
        return u == 1 ? a : -1;
    }

    /**
     * creates an n-dim normalized vector with number 1 on given row.
     * 
     * @param dim dimension
     * @param row coordinate position of 1.
     * @return new vector instance
     */
    public static Vector e(int dim, int row) {
        float d[] = new float[dim];
        d[row] = 1;
        return new Vector(d);
    }

    /**
     * invert given vector
     * 
     * @param v vector to invert
     * @return new vector instance
     */
    public static Vector invert(Vector v) {
        Vector n = v.clone(1);
        for (int i = 0; i < v.x.length; i++) {
            if (v.x[i] == 0) {
                n.x[i] = 1;
            } else {
                n.x[i] = 0;
            }
        }
        return n;
    }

    @Override
    public int compareTo(Vector o) {
        return (int) (len() - o.len());
    }

    public static List fromStream(InputStream stream) {
        Scanner sc = new Scanner(stream);
        final String CR = "\n";
        FloatArray fa = new FloatArray();
        List vlist = new LinkedList();
        while (sc.hasNext()) {
            Scanner line = new Scanner(sc.nextLine());
            //read us floats
            line.useLocale(Locale.US);
            while (line.hasNext()) {
                if (line.hasNextFloat()) {
                    fa.add(line.nextFloat());
                } else {
                    line.next();
                }
            }
            if (fa.size() > 0) {
                vlist.add(new Vector(fa.toArray()));
                fa.clear();
            }
            line.close();
        }
        sc.close();
        return vlist;
    }

    public static InputStream toStream(List vl) {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        final byte[] CR = "\n".getBytes(), TAB = "\t".getBytes();
        try {
        for (Vector v : vl) {
            for (int i = 0; i < v.dimension(); i++) {
                    stream.write(/*DecimalFormat.getInstance().format*/Float.toString(v.x[i]).getBytes());
                if (i < v.dimension() - 1)
                    stream.write(TAB);
            }
            stream.write(CR);
        }
        } catch (IOException e) {
            ManagedException.forward(e);
        } finally {
            FileUtil.close(stream, false);
        }
        return ByteUtil.getInputStream(stream.toByteArray());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy