BaseCluster.java revision f0f78449e8ab7d63894964c54b6ef390ca9ce044
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.bordeaux.services;
17
18import android.location.Location;
19import android.text.format.Time;
20import android.util.Log;
21
22import java.lang.Math;
23import java.util.ArrayList;
24
25public class BaseCluster {
26
27    public static String TAG = "BaseCluster";
28
29    protected double[] mCenter;
30
31    protected long mAvgInterval;
32    protected long mDuration;
33
34    protected static final double EARTH_RADIUS = 6378100f;
35
36    public BaseCluster() {
37    }
38
39    public BaseCluster(Location location, long avgInterval) {
40        mAvgInterval = avgInterval;
41        mCenter = getLocationVector(location);
42
43        mDuration = 0;
44    }
45
46    protected double[] getLocationVector(Location location) {
47        double vector[] = new double[3];
48        double lambda = Math.toRadians(location.getLongitude());
49        double phi = Math.toRadians(location.getLatitude());
50        vector[0] = Math.cos(lambda) * Math.cos(phi);
51        vector[1] = Math.sin(lambda) * Math.cos(phi);
52        vector[2] = Math.sin(phi);
53        return vector;
54    }
55
56    private double computeDistance(double[] vector1, double[] vector2) {
57        double product = 0f;
58        for (int i = 0; i < 3; ++i) {
59            product += vector1[i] * vector2[i];
60        }
61        double radian = Math.acos(Math.min(product, 1f));
62        return radian * EARTH_RADIUS;
63    }
64
65    /*
66     * This computes the distance from loation to the cluster center in meter.
67     */
68    public float distanceToCenter(Location location) {
69        return (float) computeDistance(mCenter, getLocationVector(location));
70    }
71
72    public float distanceToCluster(BaseCluster cluster) {
73        return (float) computeDistance(mCenter, cluster.mCenter);
74    }
75
76    public void absorbCluster(BaseCluster cluster) {
77        if (cluster.mAvgInterval != mAvgInterval) {
78            throw new RuntimeException(
79                    "aborbing cluster failed: inconsistent average invergal ");
80        }
81
82        double currWeight = ((double) mDuration) / (mDuration + cluster.mDuration);
83        double newWeight = 1f - currWeight;
84        double norm = 0;
85        for (int i = 0; i < 3; ++i) {
86            mCenter[i] = currWeight * mCenter[i] + newWeight * cluster.mCenter[i];
87            norm += mCenter[i] * mCenter[i];
88        }
89        // normalize
90        for (int i = 0; i < 3; ++i) {
91            mCenter[i] /= norm;
92        }
93        mDuration += cluster.mDuration;
94    }
95
96    public boolean passThreshold(long durationThreshold) {
97        // TODO: might want to keep semantic cluster
98        return mDuration > durationThreshold;
99    }
100}
101