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.
151 lines
3.4 KiB
151 lines
3.4 KiB
4 years ago
|
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;
|
||
|
}
|
||
|
}
|