10e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski/*
20e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * Copyright (C) 2015 The Android Open Source Project
30e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski *
40e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * Licensed under the Apache License, Version 2.0 (the "License");
50e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * you may not use this file except in compliance with the License.
60e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * You may obtain a copy of the License at
70e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski *
80e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski *      http://www.apache.org/licenses/LICENSE-2.0
90e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski *
100e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * Unless required by applicable law or agreed to in writing, software
110e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * distributed under the License is distributed on an "AS IS" BASIS,
120e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * See the License for the specific language governing permissions and
140e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski * limitations under the License
150e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski */
160e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
170e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskipackage com.android.systemui.classifier;
180e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
190e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskipublic class Point {
200e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public float x;
210e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public float y;
220e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public long timeOffsetNano;
230e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
240e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public Point(float x, float y) {
250e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        this.x = x;
260e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        this.y = y;
270e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        this.timeOffsetNano = 0;
280e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
290e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
300e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public Point(float x, float y, long timeOffsetNano) {
310e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        this.x = x;
320e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        this.y = y;
330e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        this.timeOffsetNano = timeOffsetNano;
340e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
350e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
360e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public boolean equals(Point p) {
370e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        return x == p.x && y == p.y;
380e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
390e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
400e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public float dist(Point a) {
410e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        return (float) Math.hypot(a.x - x, a.y - y);
420e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
430e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
440e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    /**
450e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski     * Calculates the cross product of vec(this, a) and vec(this, b) where vec(x,y) is the
460e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski     * vector from point x to point y
470e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski     */
480e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public float crossProduct(Point a, Point b) {
490e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        return (a.x - x) * (b.y - y) - (a.y - y) * (b.x - x);
500e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
510e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski
520e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    /**
530e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski     * Calculates the dot product of vec(this, a) and vec(this, b) where vec(x,y) is the
540e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski     * vector from point x to point y
550e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski     */
560e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    public float dotProduct(Point a, Point b) {
570e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski        return (a.x - x) * (b.x - x) + (a.y - y) * (b.y - y);
580e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski    }
5968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
6068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    /**
6168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski     * Calculates the angle in radians created by points (a, this, b). If any two of these points
6268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski     * are the same, the method will return 0.0f
6368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski     *
6468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski     * @return the angle in radians
6568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski     */
6668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    public float getAngle(Point a, Point b) {
6768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        float dist1 = dist(a);
6868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        float dist2 = dist(b);
6968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
7068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        if (dist1 == 0.0f || dist2 == 0.0f) {
7168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            return 0.0f;
7268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
7368d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski
7468d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        float crossProduct = crossProduct(a, b);
7568d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        float dotProduct = dotProduct(a, b);
7668d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        float cos = Math.min(1.0f, Math.max(-1.0f, dotProduct / dist1 / dist2));
7768d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        float angle = (float) Math.acos(cos);
7868d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        if (crossProduct < 0.0) {
7968d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski            angle = 2.0f * (float) Math.PI - angle;
8068d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        }
8168d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski        return angle;
8268d0c9b1e9f1df04b3a0e1ebb1e7ed4c18994cf3Blazej Magnowski    }
830e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski}
84