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