/* * KnownLocationPinData.java * Copyright (C) 2016 Nicholas Killewald * * This file is distributed under the terms of the BSD license. * The source package should have a LICENSE file at the toplevel. */ package net.exclaimindustries.geohashdroid.util; import android.content.Context; import android.graphics.Color; import android.support.annotation.NonNull; import com.google.android.gms.maps.model.LatLng; import net.exclaimindustries.geohashdroid.R; import java.util.Random; /** * This handles the drawn pin data used by KnownLocation and the search result * markers in KnownLocationsPicker. That is, given a LatLng, it uses that as a * hash to pick a pseudo-random color, pin angle, and pin length. */ public class KnownLocationPinData { private final double mAngle; private final float mLength; private final int mHue; /** * Creates the object and initializes the data portions. * * @param c a Context from which Resources will be derived * @param loc a LatLng to hash up */ public KnownLocationPinData(@NonNull Context c, @NonNull LatLng loc) { Random rand = makeRandom(loc); // The angle, length, and hue are thus the first three of their // respective types off the top. mAngle = Math.toRadians((rand.nextDouble() * 20.0f) + 80.0f); mLength = c.getResources().getDimension(R.dimen.known_location_pin_base_length) * (1 - (rand.nextFloat() * 0.5f)); mHue = rand.nextInt(360); } @NonNull private Random makeRandom(@NonNull LatLng loc) { // What we're looking for here is a stable randomizer with the seed // initialized to something (reasonably) unique to the location given. // So, more of a hashing function, really. java.util.Random, as the // docs assure me, will ALWAYS be a certain algorithm for portability's // sake, and thus always give the same results (they also assure me this // is specifically NOT suitable for anything having to do with security, // which sounds like what I'm looking for). // So, to generate our seed, we're going to convert the latitude and // longitude into 32-bit ints. Sort of. More like we're going to // multiply them up so they're more reasonably in the domain of // -(2^31 - 1)...2^31. Then, we bit-shift one of them such that we can // add both together into a long whose bits are reasonably unique, // giving us a seed that's reasonably unique. This is entirely the // wrong way to do this. long latPart = Double.doubleToLongBits(loc.latitude); long lonPart = Double.doubleToLongBits(loc.longitude) << 32; long seed = latPart + lonPart; return new Random(seed); } /** * Gets the angle at which the pin should be drawn, in degrees. * * @return the angle */ public double getAngle() { return mAngle; } /** * Gets the length of the pin. The pin's head should have its center be * at the vertical end of the pin itself. * * @return the pin length */ public float getLength() { return mLength; } /** * Gets the pin's hue. * * @return the hue */ public int getHue() { return mHue; } /** * Gets the actual pin color. * * @return the color */ public int getColor() { return Color.HSVToColor(new float[]{mHue, 1.0f, 0.8f}); } }