Sketcher2 source code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
3.4 KiB

package com.jotuntech.sketcher.client;
import java.util.ArrayList;
import java.util.List;
import com.jotuntech.sketcher.common.Input;
/**
* Static singleton for input interpolation.
*
* @author Thor Harald Johansen
*/
public class Smoother {
/* Smoothing threshold */
private static float threshold = 4f;
private static float smoothness = 1.5f;
private static boolean enabled = true;
Input[] cursor = new Input[] {new Input(), new Input(), new Input()};
/**
* Sets all points to given input
* @param d input to add.
*/
public void set(Input d) {
cursor[0] = d;
cursor[1] = cursor[0];
cursor[2] = cursor[1];
}
public void setPressure(int pressure) {
//cursor[0].pressure = pressure;
//cursor[1].pressure = pressure;
//cursor[2].pressure = pressure;
}
/**
* Adds a new input for smoothing.
*
* @param d input to add.
*/
public void add(Input d) {
float dx = d.x - cursor[2].x;
float dy = d.y - cursor[2].y;
float dd = d.pressure - cursor[2].pressure;
float h = (float)Math.hypot(dx, dy);
float d2 = h - smoothness;
if(d2 > 0) {
float sx = dx * d2 / h;
float sy = dy * d2 / h;
float sd = dd * d2 / h;
cursor[0] = cursor[1];
cursor[1] = cursor[2];
cursor[2] = new Input(cursor[2].x + sx, cursor[2].y + sy, (int)(cursor[2].pressure + sd));
}
}
/**
* Return a list of smoothed inputs.
*
* @return List of smoothed inputs.
*/
public List<Input> get() {
/* Create list for inputs. */
List<Input> inputs = new ArrayList<Input>();
if(enabled) {
/* Segment cursor. */
segment(inputs, cursor[0], cursor[1], cursor[2]);
} else {
inputs.add(cursor[2]);
}
return inputs;
}
public Input getIndex(int index) {
return cursor[index];
}
// uses a, b and c to interpolate inputs between b and c, store in inputs.
void segment(List<Input> inputs, Input a, Input b, Input c) {
// difference AB & BC
Input dab = a.difference(b);
Input dbc = b.difference(c);
// magnitude AB & BC
float mab = (float)Math.hypot(dab.x, dab.y);
float mbc = (float)Math.hypot(dbc.x, dbc.y);
// orientation AB & BC
float oab = (float)Math.acos(dab.x / mab) * (dab.y < 0 ? -1 : 1);
float obc = (float)Math.acos(dbc.x / mbc) * (dbc.y < 0 ? -1 : 1);
// normalize
if(obc - oab > Math.PI || obc - oab < -Math.PI) {
obc -= Math.PI * 2;
}
// angle ABC
float abc = Math.abs(obc - oab);
// threshold of operation
if(mbc * abc > threshold && abc < Math.PI / 2) {
// three-quarter of angle ABC
float angle = (oab + (obc * 3)) / 4;
// half of magnitude BC
Input d = new Input(b.x + ((float)Math.cos(angle) * mbc / 2), b.y
+ ((float)Math.sin(angle) * mbc / 2), (b.pressure + c.pressure) / 2);
segment(inputs, a, b, d);
inputs.add(d);
segment(inputs, b, d, c);
} else {
inputs.add(c);
}
}
public static void setThreshold(float threshold) {
Smoother.threshold = threshold;
}
public static float getThreshold() {
return threshold;
}
public static void setSmoothness(float smoothness) {
Smoother.smoothness = smoothness;
}
public static float getSmoothness() {
return smoothness;
}
public static void setEnabled(boolean enabled) {
Smoother.enabled = enabled;
}
public static boolean isEnabled() {
return enabled;
}
}