Utils essentials

I thought I’d try to get some snowball rolling here.

Rules are simple: Post a single static method “Utils” method that you find useful. Hopefully we’ll have tons of methods in here that people can copy and paste to use in their own Utils classes.

These methods can be many things, but they deal with a set of parameters and return a single value.

Keep the name of the method very descriptive, not just “getBla”, but “calculateBlaFromSetOfBlahblahs”.

I’ll start with a couple of methods:


// Linear interpolation, get the value between a and b where t is 0-1.
public static float lerp(float a, float b, float t) {
	if (t < 0)
		return a;
	return a + t * (b - a);
}


// Get the euclidean distance between two points.
public static float euclideanDistance(float x1, float y1, float x2, float y2) {
	return (float) Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}

Both of these can probably be optimized, so go ahead and post your optimized version.

Funny thread :slight_smile:

In your example, for t=0 you currently do the full calculation, while you can just return “a”.

I’ll add a method of my own. It can be used to store application data files in the proper location for the current platform. You could use java.util.prefs, but in some cases you just want a place to store files.


/**
 * Returns a {@code File} that points to the application data with the 
 * specified path. The directory returned will be a subdirectory with
 * the application's name, in the platform-specific location for storing
 * application data. If the subdirectory does not already exist it is
 * created.
 * @param appName The name of the application.
 * @param path Relative path to the requested file.
 * @return A {@code File} object that points to the requested file.
 * @throws IllegalArgumentException if the path is empty or absolute.
 */
public static File getApplicationData(String appName, String path) {

    if (appName.length() == 0) {
        throw new IllegalArgumentException("Invalid application name");
    }
        
    if ((path.length() == 0) || path.startsWith("/")) {
        throw new IllegalArgumentException("Invalid path: " + path);
    }

    File appdir = null;
        
    if (System.getProperty("os.name").startsWith("Windows")) { 
        appdir = new File(System.getenv("APPDATA"));
    } else if (System.getProperty("os.name").startsWith("Mac OS X")) {
        // This will also work for non-English versions of Mac OS X
        appdir = new File(System.getenv("HOME") + "/Library/Application Support"); 
    }
    
    // If auto-detection failed, or if not known, fall back to user home
    if ((appdir == null) || !appdir.exists() || !appdir.isDirectory()) {
        appdir = new File(System.getProperty("user.home"));
        appName = "." + appName;
    }
        
    File dir = new File(appdir, appName);
    if (!dir.exists()) {
        boolean success = dir.mkdir();
        if (!success) {
            throw new IllegalStateException("Cannot create directory: " + dir.getAbsolutePath());
        }
    }
        
    return new File(dir.getAbsolutePath() + "/" + path);
}

If we are talking about interpolation, then I have a few as well :slight_smile:


public static final float interpolateHermite(float v0, float v1, float v2, float v3, float v01time, float v12time, float x, float tension, float bias){
       float mu2 = x * x;
       float mu3 = mu2 * x;

       float ts, td, a0, a1, a2, a3;
       
       ts  = (v1 - v0) * (((1f + bias) * (1f - tension)) / 2f);
       ts += (v2 - v1) * (((1f - bias) * (1f - tension)) / 2f);
       
       td  = (v2 - v1) * (((1f + bias) * (1f - tension)) / 2f);
       td += (v3 - v2) * (((1f - bias) * (1f - tension)) / 2f);

       a0  =  2f * mu3 - 3f * mu2 + 1f;
       a1  =       mu3 - 2f * mu2 + x;
       a2  =       mu3 -      mu2;
       a3  = -2f * mu3 + 3f * mu2;

       return a0 * v1 
            + a1 * ts 
            + a2 * td 
            + a3 * v2;
    }


public static final float interpolateCatmullRom(float v0, float v1, float v2, float v3, float x){
        return 0.5f * ((-v0 + 3f*v1 -3f*v2 + v3)*x*x*x
                    +  (2f*v0 -5f*v1 + 4f*v2 - v3)*x*x
                    +  (-v0+v2)*x
                    +  2f*v1);

    }


    public static final float interpolateCubic(float v0, float v1, float v2, float v3, float x){
        float p = (v3 - v2) - (v0 - v1);
        float q = (v0 - v1) - p;
        float r = v2 - v0;
        float s = v1;

        return p * x * x * x 
             + q * x * x 
             + r * x 
             + s;
    }


    public static final float interpolateCosine(float v0, float v1, float x){
        float ft = x * (float)Math.PI;
        float f = (1 - (float)Math.cos(ft)) * 0.5f;

        return v0 * (1 - f) + v1 * f;
    }

Some noise

public static final float noise1(int x){
       x = (x << 13) ^ x;
       x = (x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff;
       return 1.0f - x / 1073741824.0f;
    }

    public static final float noiseSmooth1(int x){
       return noise1(x) / 2.0f + noise1(x-1) / 4.0f + noise1(x+1) / 4.0f;
    }

Not sure where I got it from, but hopefully there’s no copyright on functions lol

Superb! I smell a good thread coming out of this.

Please remember to add a comment describing the function, e.g.:

// This function interpolates … by taking x1, y1, etc., and returning a processed value…

A generic toString for debugging output with arrays:

	public static String toString(Object obj)
	{
		if (obj instanceof Object[])
		{
			StringBuilder sb = new StringBuilder();
			sb.append("[");
			boolean first = true;
			for (Object o : (Object[])obj)
			{
				if (first) first = false;
				else sb.append(", ");
				sb.append(toString(o));
			}
			return sb.append("]").toString();
		}
		if (obj instanceof int[]) return Arrays.toString((int[])obj);
		if (obj instanceof long[]) return Arrays.toString((long[])obj);
		if (obj instanceof short[]) return Arrays.toString((short[])obj);
		if (obj instanceof byte[]) return Arrays.toString((byte[])obj);
		if (obj instanceof double[]) return Arrays.toString((double[])obj);
		if (obj instanceof float[]) return Arrays.toString((float[])obj);
		if (obj instanceof boolean[]) return Arrays.toString((boolean[])obj);
		return obj == null ? "null" : obj.toString();
	}

A wrapper around Color.HSBtoRGB which works around a bug I reported 7.5 years ago.

	public static int HSBtoRGB(float hue, float saturation, float brightness)
	{
		// Fix for bug 4759386.
		float h = (hue - (float)Math.floor(hue)) * 6f;
		if (h >= 6f) hue = 0f;
		return Color.HSBtoRGB(hue, saturation, brightness);
	}

And one more for now: a method I’ve found very helpful for working out why my OpenGL scene isn’t rendering as I think it should:

	/**
	 * Gets a string representing the current lighting state.
	 * @param gl The OpenGL handle.
	 * @return A string which describes the current lights at a basic level.
	 */
	public static String lightingDebugString(GL gl)
	{
		// First thing to check: are we actually doing lighting at all?
		boolean lighting = gl.glIsEnabled(GL.GL_LIGHTING);
		if (!lighting)
		{
			return "Lighting is disabled; glColor controls vertex colours";
		}

		// Ok. We'll assemble stuff.
		StringBuilder sb = new StringBuilder();
		sb.append("Lighting is enabled\n");
		float[] buf = new float[4];

		// Global stuff. There are more parameters, but this is sufficient for
		// now. Maybe this method should have a verbosity parameter?
		gl.glGetFloatv(GL.GL_LIGHT_MODEL_AMBIENT, buf, 0);
		sb.append("\tScene ambient light: ");
		append(sb, buf);
		sb.append("\n");

		// How many lights must we check?
		int[] ibuf = new int[1];
		gl.glGetIntegerv(GL.GL_MAX_LIGHTS, ibuf, 0);
		int numLights = ibuf[0];

		// List info for the enabled lights.
		sb.append("\tEnabled lights:\n");
		int enabledLightCount = 0;
		for (int i = 0; i < numLights; i++)
		{
			// Note that it is always the case that GL_LIGHT_i = GL_LIGHT0 + i:
			// ref. http://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml
			if (gl.glIsEnabled(GL.GL_LIGHT0 + i))
			{
				enabledLightCount++;
				sb.append("\t\tLight ").append(i).append("\n");

				// Key light parameters. Ignoring things like GL_SPOT_EXPONENT.
				gl.glGetLightfv(GL.GL_LIGHT0 + i, GL.GL_AMBIENT, buf, 0);
				sb.append("\t\t\tAmbient: ");
				append(sb, buf);
				sb.append("\n");

				gl.glGetLightfv(GL.GL_LIGHT0 + i, GL.GL_DIFFUSE, buf, 0);
				sb.append("\t\t\tDiffuse: ");
				append(sb, buf);
				sb.append("\n");

				gl.glGetLightfv(GL.GL_LIGHT0 + i, GL.GL_POSITION, buf, 0);
				sb.append("\t\t\tPosition: ");
				append(sb, buf);
				sb.append("\n");

				sb.append("\t\t\tOther parameters snipped");
			}
		}

		// If no lights enabled, say so.
		if (enabledLightCount == 0)
		{
			sb.append("\t\tNone");
		}

		return sb.toString();
	}

	/**
	 * Utility method to append a float[] to a StringBuilder.
	 * @param sb The string builder to which to append.
	 * @param vals The array to append.
	 */
	private static void append(StringBuilder sb, float[] vals)
	{
		sb.append("[");
		for (int i = 0; i < vals.length; i++)
		{
			if (i > 0)
			{
				sb.append(", ");
			}
			sb.append(vals[i]);
		}
		sb.append("]");
	}

Edit: Damn, the “evaluation” section isn’t even filled in, which probably means that no Sun employee has ever looked into this! :o

http://code.google.com/p/bookjar-utils/source/browse/BookJar-utils/src/util/io/IoUtils.java

http://code.google.com/p/bookjar-utils/source/browse/BookJar-utils/src/util/threads/Threads.java

It’s probably already in the JRE but never find it.

        /**
	 * The angle of the vector (x, y). The angle is between 0 and 2*PI.
	 * @param x The x value of the vector.
	 * @param y The y value of the vector.
	 * @return The angle of the vector (x, y).
	 */
	public static double findAngle(double x, double y){
		double theta = 0;
		if(x == 0){
			if(y>0){
				theta = Math.PI/2;
			}else if(y < 0){
				theta = Math.PI*3/2;
			}
		}
		if(x > 0){
			theta = Math.atan(y/Math.abs(x));
		}
		if(x < 0){
			theta = Math.PI - Math.atan(y/Math.abs(x));
		}

		if(theta < 0){
			theta += Math.PI*2;
		}
		return theta;
	}

Good thread.

I think what you are looking for is: Math.atan2(y, x);
Except for that it is from -PI to PI IIRC.

hehe probably from hugo elias website :wink: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm (NB : those lack of optimisation are hurting my eyes : /2 => * 0.5 , /constante => *1.0/constante ; unnecessary float cast :frowning: )

anyway nice thread

Here’s a nice self-contained snippet from Rebirth, to make a shallow copy from one object to an already existing one. Useful for dynamically reloading an object when it’s on-disk state changes.

public static void shallowCopy(Object source, Object dest, final boolean publicOnly)
	{
		if (!source.getClass().isInstance(dest))
			throw new IllegalArgumentException();
		
		Field[] sourceFields = ReflectionUtil.getAllDeclaredFields(source, publicOnly);
		for (int i=0; i<sourceFields.length; i++)
		{
			try
			{
				Field f = sourceFields[i];
				
				final int mods = f.getModifiers();
				if (Modifier.isStatic(mods) || Modifier.isFinal(mods))
					continue;
				
				f.setAccessible(true);
				
				Object sourceValue = f.get(source);
				f.set(dest, sourceValue);
			}
			catch (IllegalArgumentException e)
			{
				e.printStackTrace();
			}
			catch (IllegalAccessException e)
			{
				e.printStackTrace();
			}
		}
	}

	/** 'publicOnly' just gets public fields (Class.getFields vs. Class.getDeclaredFields) so we can work with reduced
	 *  functionality in a sandboxed environment (ie. applets)
	 */
	public static Field[] getAllDeclaredFields(Object object, final boolean publicOnly)
	{
		ArrayList<Field> result = new ArrayList<Field>();
		
		Class<?> clazz = object.getClass();
		while (clazz != null)
		{
			Field[] fields;
			if (publicOnly)
				fields = clazz.getFields();
			else
				fields = clazz.getDeclaredFields();
			
			for (int i=0; i<fields.length; i++)
				result.add(fields[i]);
			
			clazz = clazz.getSuperclass();
		}
		
		return result.toArray(new Field[result.size()]);
	}

Funny thing that you are coding for unsigned applets, yet Field.setAccessible(true) will always throw a SecurityException, regardless of whether the field is ‘already’ public.

You made him change perfectly fast lerp-code, adding a branch that will probably suck all the speed out of it.


// Getting position in a quadratic bezier
// Usage: x = quadraticBezier(x1, x2, x3, 0.5f) and y = quadraticBezier(y1,y2,y3,0.5f)
// Returns the x,y point at 0.5 in the curve.
public static float quadraticBezier(float a, float b, float c, float t) {
	return (((1f - t) * (1f - t)) * a) + (((2f * t) * (1f - t)) * b) + ((t * t) * c);
}

These are a set of rotation functions.

They essentially rotate a point around a pivot point given an angle, where angle is in degrees.

	public static float getRotatedX(float currentX, float currentY, float pivotX, float pivotY, float angle) {
		float x = currentX-pivotX;
		float y = currentY-pivotY;
		float a = (float) Math.toRadians(angle);
		float xr = (float) ((x * Math.cos(a)) - (y * Math.sin(a)));
		return xr+pivotX;
	}
	
	public static float getRotatedY(float currentX, float currentY, float pivotX, float pivotY, float angle) {
		float x = currentX-pivotX;
		float y = currentY-pivotY;
		float a = (float) Math.toRadians(angle);
		float yr = (float) ((x * Math.sin(a)) + (y * Math.cos(a)));
		return yr+pivotY;
	}

Nope. The above code works just fine in an unsigned applet (whereas the previous version, without the ‘publicOnly’ would throw a security exception).

@Appel:

For a base version of lerp, I’d suggest skipping all range checking and allow extrapolation for t outside of [0,1]:


public static float lerp(float a, float b, float t) 
{
  return a + t * (b - a);
}

For performance reasons, usage of Math.pow should be avoided when the exponent is known, esp for small exponents:


public static float euclideanDistance2D(float x1, float y1, float x2, float y2)
{
  float dx = x1-x2;
  float dy = y1-y2; 

  return (float)Math.sqrt(dx*dx + dy*dy);
}

It’s also worth noting that distance squared is as good a metric as distance, so this can be used in many instances (esp for compares):


public static float euclideanDistanceSq2D(float x1, float y1, float x2, float y2)
{
  float dx = x1-x2;
  float dy = y1-y2; 

  return dx*dx + dy*dy;
}

@Momoko_Fan:

All the common Java compiler do not perform common-expression removal, so IMHO it’s a good idea to manually perform.

I’d also suggest converting polynomial evaluations into Horner form:


public static final float interpolateCubic(float v0, float v1, float v2, float v3, float x)
{
  float p = (v3 - v2) - (v0 - v1);
  float q = (v0 - v1) - p;
  float r = v2 - v0;
  float s = v1;

  return ((p*x + q)* x + r)*x + s;
}

He didn’t change it yet. But I assume that this means the currently existing branch for t < 0 is also slowing it down. I’m not even sure why this exists, considering the input is assumed to be between 0 and 1. If it’s guarding for invalid input, why isn’t there a check for inputs > 1?