package ini.trakem2.display;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
public class FreeHandProfile {
private Profile profile;
private boolean updateProfile = true;
private double[][] all_points; // points {{x0,y0},{x1,y1} , ... , {xn,yn}}
// painted originally
private int lastBezierIndex; // index in all_points where last time used
// to insert bezier
private int nPoints = 0;
private double[][] l_points; // points {{x0,y0},{x1,y1} , ... , {xn,yn}}
// left bezier points
private double[][] r_points; // points {{x0,y0},{x1,y1} , ... , {xn,yn}}
// right bezier points
private double[][] b_points; // points {{x0,y0},{x1,y1} , ... , {xn,yn}}
// center bezier points
private boolean insertAtBeginOfProfile;
private boolean insertAtEndOfProfile;
private int nBeziers = 0;
private boolean isVisible = true;
private double mouseVelocity[] = new double[2];
private double mousePosition[] = new double[2];
private int[] bezierMousePoxIndexes; // points {{x0,y0},{x1,y1} , ... ,
// {xn,yn}}
private static final double MOUSE_MASS = 10;
private double[][] newBezierPoints = new double[4][2];
//only used in closed beziers
private int startIndex;
private static final double MAX_ACCUMULATED_ERROR_PER_BEZIER = 0.3;
private static final int GRADIENT_DESCENT_SAMPLE_COUNT = 20;
private static final double LEARNING_RATE = 0.1;
public FreeHandProfile(Profile profile) {
this.profile = profile;
}
public void mousePressed(int x_p, int y_p) {
// array initialisation
// mousePosition[0] = x_p;
// mousePosition[1] = y_p;
x_p -= profile.getX();
y_p -= profile.getY();
all_points = new double[5][2];
l_points = new double[5][2];
r_points = new double[5][2];
b_points = new double[5][2];
bezierMousePoxIndexes = new int[5];
if (profile.hasPoints()) {
if (profile.isClosed()) {
startIndex = profile.getNearestPointIndex(x_p,y_p);
all_points[0][0] = profile.p[0][startIndex];
all_points[0][1] = profile.p[1][startIndex];
l_points[0][0] = profile.p_l[0][startIndex];
l_points[0][1] = profile.p_l[1][startIndex];
b_points[0][0] = profile.p[0][startIndex];
b_points[0][1] = profile.p[1][startIndex];
r_points[0][0] = profile.p_r[0][startIndex];
r_points[0][1] = profile.p_r[1][startIndex];
} else {
double[][] first = profile.getFirstPoint();
double[][] last = profile.getLastPoint();
double[][] nearer;
double firstDist = squaredDist(first[1][0], first[1][1], x_p, y_p);
double lastDist = squaredDist(last[1][0], last[1][1], x_p, y_p);
if (firstDist < lastDist) {
// minDist = firstDist;
insertAtBeginOfProfile = true;
nearer = first;
} else {
insertAtEndOfProfile = true;
nearer = last;
}
all_points[0][0] = nearer[1][0];
all_points[0][1] = nearer[1][1];
l_points[0][0] = nearer[0][0];
l_points[0][1] = nearer[0][1];
b_points[0][0] = nearer[1][0];
b_points[0][1] = nearer[1][1];
r_points[0][0] = nearer[2][0];
r_points[0][1] = nearer[2][1];
}
} else {
all_points[0][0] = x_p;
all_points[0][1] = y_p;
l_points[0][0] = r_points[0][0] = b_points[0][0] = x_p;
l_points[0][1] = r_points[0][1] = b_points[0][1] = y_p;
}
// all_points[1][0] = x_p;
// all_points[1][1] = y_p;
// nPoints = 2;
mousePosition[0] = all_points[0][0] + profile.getX();
mousePosition[1] = all_points[0][1] + profile.getY();
bezierMousePoxIndexes[0] = 0;
for (int i = 0; i < 4; i++) {
this.newBezierPoints[i][0] = all_points[0][0];
this.newBezierPoints[i][1] = all_points[0][1];
}
nPoints = 1;
nBeziers = 1;
lastBezierIndex = 0;
}
public void mouseDragged(MouseEvent me, int x_d, int y_d, double dx, double dy) {
mouseVelocity[0] = dx / MOUSE_MASS + (1 - 1d / MOUSE_MASS) * mouseVelocity[0];
mouseVelocity[1] = dy / MOUSE_MASS + (1 - 1d / MOUSE_MASS) * mouseVelocity[1];
mousePosition[0] += mouseVelocity[0];
mousePosition[1] += mouseVelocity[1];
insertPoint(mousePosition[0] - profile.getX(), mousePosition[1] - profile.getY());
adjustNewBezierEndPoint();
double[][] targetPoints = calculateMouseSamples(lastBezierIndex, nPoints - 1);
interpolateTargetSamples(targetPoints, 20);
double medError = getMedSquaredError(targetPoints);
if (medError > MAX_ACCUMULATED_ERROR_PER_BEZIER && (nPoints - lastBezierIndex > 20)) {
fixateCurrentBezier();
if (nBeziers > 3)
smoothBezierPoint(nBeziers - 2);
}
}
public void mouseReleased(MouseEvent me, int x_p, int y_p, int x_d, int y_d, int x_r, int y_r) {
adjustNewBezierEndPoint();
double[][] targetPoints = calculateMouseSamples(lastBezierIndex, nPoints - 1);
interpolateTargetSamples(targetPoints, 20);
fixateCurrentBezier();
if (nBeziers > 3)
smoothBezierPoint(nBeziers - 2);
r_points[nBeziers - 1][0] = b_points[nBeziers - 1][0];
r_points[nBeziers - 1][1] = b_points[nBeziers - 1][1];
if (updateProfile) {
double[][] tmp_p_l = new double[2][nBeziers];
double[][] tmp_p = new double[2][nBeziers];
double[][] tmp_p_r = new double[2][nBeziers];
if (insertAtBeginOfProfile) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < nBeziers; j++) {
tmp_p_r[i][j] = l_points[nBeziers - 1 - j][i];
tmp_p[i][j] = b_points[nBeziers - 1 - j][i];
tmp_p_l[i][j] = r_points[nBeziers - 1 - j][i];
}
}
profile.addPointsAtBegin(tmp_p_l, tmp_p, tmp_p_r);
} else if (insertAtEndOfProfile) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < nBeziers; j++) {
tmp_p_l[i][j] = l_points[j][i];
tmp_p[i][j] = b_points[j][i];
tmp_p_r[i][j] = r_points[j][i];
}
}
profile.addPointsAtEnd(tmp_p_l, tmp_p, tmp_p_r);
} else {
if(profile.closed && profile.hasPoints())
{
int endIndex = profile.getNearestPointIndex(this.all_points[this.nPoints-1][0], this.all_points[this.nPoints-1][1]);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < nBeziers; j++) {
tmp_p_l[i][j] = l_points[j][i];
tmp_p[i][j] = b_points[j][i];
tmp_p_r[i][j] = r_points[j][i];
}
}
profile.insertBetween(startIndex, endIndex,tmp_p_l, tmp_p, tmp_p_r);
}
else
{
for (int i = 0; i < 2; i++) {
for (int j = 0; j < nBeziers; j++) {
tmp_p_l[i][j] = l_points[j][i];
tmp_p[i][j] = b_points[j][i];
tmp_p_r[i][j] = r_points[j][i];
}
}
profile.setPoints(tmp_p_l, tmp_p, tmp_p_r);
}
}
}
// update x,y,width,height
profile.calculateBoundingBox(true);
profile.repaint(false);
}
private void smoothBezierPoint(int i) {
double[][] bezier1 = new double[4][2]; // bezier points defining the
// first curve
double[][] bezier2 = new double[4][2]; // bezier points defining the
// second curve
int firstMousePointIndex = bezierMousePoxIndexes[i - 1];
int middleMousePointIndex = bezierMousePoxIndexes[i];
int lastMousePointIndex = bezierMousePoxIndexes[i + 1];
double[][] targetpoints1 = calculateMouseSamples(firstMousePointIndex, middleMousePointIndex);
double[][] targetpoints2 = calculateMouseSamples(middleMousePointIndex, lastMousePointIndex);
bezier1[0][0] = b_points[i - 1][0];
bezier1[0][1] = b_points[i - 1][1];
bezier1[1][0] = r_points[i - 1][0];
bezier1[1][1] = r_points[i - 1][1];
bezier1[2][0] = l_points[i][0];
bezier1[2][1] = l_points[i][1];
bezier1[3][0] = b_points[i][0];
bezier1[3][1] = b_points[i][1];
bezier2[0][0] = b_points[i][0];
bezier2[0][1] = b_points[i][1];
bezier2[1][0] = r_points[i][0];
bezier2[1][1] = r_points[i][1];
bezier2[2][0] = l_points[i + 1][0];
bezier2[2][1] = l_points[i + 1][1];
bezier2[3][0] = b_points[i + 1][0];
bezier2[3][1] = b_points[i + 1][1];
smoothBezier(bezier1, bezier2, targetpoints1, targetpoints2);
b_points[i - 1][0] = bezier1[0][0];
b_points[i - 1][1] = bezier1[0][1];
r_points[i - 1][0] = bezier1[1][0];
r_points[i - 1][1] = bezier1[1][1];
l_points[i][0] = bezier1[2][0];
l_points[i][1] = bezier1[2][1];
b_points[i][0] = bezier1[3][0];
b_points[i][1] = bezier1[3][1];
b_points[i][0] = bezier2[0][0];
b_points[i][1] = bezier2[0][1];
r_points[i][0] = bezier2[1][0];
r_points[i][1] = bezier2[1][1];
l_points[i + 1][0] = bezier2[2][0];
l_points[i + 1][1] = bezier2[2][1];
b_points[i + 1][0] = bezier2[3][0];
b_points[i + 1][1] = bezier2[3][1];
}
// bezier1 and 2 are also return values !!
private void smoothBezier(double[][] bezier1, double[][] bezier2, double[][] targetpoints1, double[][] targetpoints2) {
double alpha;
double beta;
double[] dP;
double[] p00;
double[] p02;
double[] p03;
double[] p10;
double[] p11;
// take star points
p03 = bezier1[0];
p02 = bezier1[1];
p11 = bezier2[2];
p10 = bezier2[3];
p00 = new double[2];
p00[0] = bezier2[0][0];
p00[1] = bezier2[0][1];
// find good start points for other values
dP = new double[2];
dP[0] = bezier1[2][0] - bezier2[1][0];
dP[1] = bezier1[2][1] - bezier2[1][1];
alpha = dist(bezier1[2][0], bezier1[2][1], p00[0], p00[1]) / dist(0, 0, dP[0], dP[1]);
beta = -dist(bezier2[1][0], bezier2[1][1], p00[0], p00[1]) / dist(0, 0, dP[0], dP[1]);
for (int i = 0; i < 20; i++)// curve approximation
{
double dAlpha = 0;
double dBeta = 0;
double[] ddP = new double[2];
double[] dp02 = new double[2];
double[] dp00 = new double[2];
double[] dp11 = new double[2];
// calc gradients for first curve
for (int j = 0; j < GRADIENT_DESCENT_SAMPLE_COUNT; j++) {
double t = (j + 1) / (GRADIENT_DESCENT_SAMPLE_COUNT + 1);
// calculate part which is for all gradients the same
double constPartX = -targetpoints1[j][0];
constPartX += p00[0] * t * t * (3 - 2 * t);
constPartX += 3 * alpha * dP[0] * t * t * (1 - t);
constPartX += 3 * p02[0] * t * (1 - t) * (1 - t);
constPartX += p03[0] * (1 - t) * (1 - t) * (1 - t);
double constPartY = -targetpoints1[j][1];
constPartY += p00[1] * t * t * (3 - 2 * t);
constPartY += 3 * alpha * dP[1] * t * t * (1 - t);
constPartY += 3 * p02[1] * t * (1 - t) * (1 - t);
constPartY += p03[1] * (1 - t) * (1 - t) * (1 - t);
dAlpha += 3 * (constPartX * dP[0] + constPartY * dP[1]) * t * t * (1 - t);
ddP[0] += 3 * constPartX * alpha * t * t * (1 - t);
ddP[1] += 3 * constPartY * alpha * t * t * (1 - t);
dp02[0] += 3 * constPartX * t * (1 - t) * (1 - t);
dp02[1] += 3 * constPartY * t * (1 - t) * (1 - t);
dp00[0] += constPartX * t * t * (3 - 2 * t);
dp00[1] += constPartY * t * t * (3 - 2 * t);
}
// calc gradients for second curve
for (int j = 0; j < GRADIENT_DESCENT_SAMPLE_COUNT; j++) {
double t = 1 - ((j + 1) / (GRADIENT_DESCENT_SAMPLE_COUNT + 1));
// calculate part which is for all gradients the same
double constPartX = -targetpoints2[j][0];
constPartX += p00[0] * t * t * (3 - 2 * t);
constPartX += 3 * beta * dP[0] * t * t * (1 - t);
constPartX += 3 * p11[0] * t * (1 - t) * (1 - t);
constPartX += p10[0] * (1 - t) * (1 - t) * (1 - t);
double constPartY = -targetpoints2[j][1];
constPartY += p00[1] * t * t * (3 - 2 * t);
constPartY += 3 * beta * dP[1] * t * t * (1 - t);
constPartY += 3 * p11[1] * t * (1 - t) * (1 - t);
constPartY += p10[1] * (1 - t) * (1 - t) * (1 - t);
dBeta += 3 * (constPartX * dP[0] + constPartY * dP[1]) * t * t * (1 - t);
ddP[0] += 3 * constPartX * beta * t * t * (1 - t);
ddP[1] += 3 * constPartY * beta * t * t * (1 - t);
dp11[0] += 3 * constPartX * t * (1 - t) * (1 - t);
dp11[1] += 3 * constPartY * t * (1 - t) * (1 - t);
dp00[0] += constPartX * t * t * (3 - 2 * t);
dp00[1] += constPartY * t * t * (3 - 2 * t);
}
alpha -= LEARNING_RATE * dAlpha;
beta -= LEARNING_RATE * dBeta;
dP[0] -= LEARNING_RATE * ddP[0];
dP[1] -= LEARNING_RATE * ddP[1];
p02[0] -= LEARNING_RATE * dp02[0];
p02[1] -= LEARNING_RATE * dp02[1];
p00[0] -= LEARNING_RATE * dp00[0];
p00[1] -= LEARNING_RATE * dp00[1];
p11[0] -= LEARNING_RATE * dp11[0];
p11[1] -= LEARNING_RATE * dp11[1];
}
bezier1[0] = p03;
bezier1[1] = p02;
bezier1[2][0] = p00[0] + alpha * dP[0];
bezier1[2][1] = p00[1] + alpha * dP[1];
bezier1[3][0] = p00[0];
bezier1[3][1] = p00[1];
bezier2[0][0] = p00[0];
bezier2[0][1] = p00[1];
bezier2[1][0] = p00[0] + beta * dP[0];
bezier2[1][1] = p00[1] + beta * dP[1];
bezier2[2] = p11;
bezier2[3] = p10;
}
private void fixateCurrentBezier() {
//if endpoint = startpoint
if (this.newBezierPoints[3][0] == this.newBezierPoints[0][0]
&& this.newBezierPoints[3][1] == this.newBezierPoints[0][1]) {
return;
}
// ensure array size
if (nBeziers >= b_points.length) {
double[][] tmp = new double[b_points.length + 5][2];
System.arraycopy(b_points, 0, tmp, 0, b_points.length);
b_points = tmp;
tmp = new double[l_points.length + 5][2];
System.arraycopy(l_points, 0, tmp, 0, l_points.length);
l_points = tmp;
tmp = new double[r_points.length + 5][2];
System.arraycopy(r_points, 0, tmp, 0, r_points.length);
r_points = tmp;
int[] tmp2 = new int[bezierMousePoxIndexes.length + 5];
System.arraycopy(bezierMousePoxIndexes, 0, tmp2, 0, bezierMousePoxIndexes.length);
bezierMousePoxIndexes = tmp2;
}
b_points[nBeziers - 1][0] = this.newBezierPoints[3][0];
b_points[nBeziers - 1][1] = this.newBezierPoints[3][1];
r_points[nBeziers - 1][0] = this.newBezierPoints[2][0];
r_points[nBeziers - 1][1] = this.newBezierPoints[2][1];
l_points[nBeziers][0] = this.newBezierPoints[1][0];
l_points[nBeziers][1] = this.newBezierPoints[1][1];
b_points[nBeziers][0] = this.newBezierPoints[0][0];
b_points[nBeziers][1] = this.newBezierPoints[0][1];
lastBezierIndex = nPoints - 1;
bezierMousePoxIndexes[nBeziers] = lastBezierIndex;
nBeziers++;
for (int i = 0; i < 4; i++) {
newBezierPoints[i][0] = newBezierPoints[0][0];
newBezierPoints[i][1] = newBezierPoints[0][1];
}
}
private double getMedSquaredError(double[][] targetPoints) {
double ret = 0;
for (int i = 0; i < GRADIENT_DESCENT_SAMPLE_COUNT; i++) {
double t = (double) (i + 1) / (GRADIENT_DESCENT_SAMPLE_COUNT + 1);
double oneMinT = 1 - t;
double dx = newBezierPoints[0][0] * t * t * t;
dx += 3 * newBezierPoints[1][0] * t * t * oneMinT;
dx += 3 * newBezierPoints[2][0] * t * oneMinT * oneMinT;
dx += newBezierPoints[3][0] * oneMinT * oneMinT * oneMinT;
dx -= targetPoints[i][0];
dx = dx * dx;
double dy = newBezierPoints[0][1] * t * t * t;
dy += 3 * newBezierPoints[1][1] * t * t * oneMinT;
dy += 3 * newBezierPoints[2][1] * t * oneMinT * oneMinT;
dy += newBezierPoints[3][1] * oneMinT * oneMinT * oneMinT;
dy -= targetPoints[i][1];
dy = dy * dy;
ret += dx + dy;
}
return ret / GRADIENT_DESCENT_SAMPLE_COUNT;
}
private void interpolateTargetSamples(double[][] targetPoints, int stepCount) {
for (int i = 0; i < stepCount; i++) {
gradientDescentStep(targetPoints);
}
}
private void gradientDescentStep(double[][] targetPoints) {
double dX1 = 0;
double dX2 = 0;
double dY1 = 0;
double dY2 = 0;
// summed gradient
for (int i = 0; i < GRADIENT_DESCENT_SAMPLE_COUNT; i++) {
double t = (double) (i + 1) / (GRADIENT_DESCENT_SAMPLE_COUNT + 1);
double oneMinT = 1 - t;
double tmp = newBezierPoints[0][0] * t * t * t;
tmp += 3 * newBezierPoints[1][0] * t * t * oneMinT;
tmp += 3 * newBezierPoints[2][0] * t * oneMinT * oneMinT;
tmp += newBezierPoints[3][0] * oneMinT * oneMinT * oneMinT;
tmp -= targetPoints[i][0];
tmp *= 6 * t * oneMinT;
dX1 += tmp * t;
dX2 += tmp * oneMinT;
tmp = newBezierPoints[0][1] * t * t * t;
tmp += 3 * newBezierPoints[1][1] * t * t * oneMinT;
tmp += 3 * newBezierPoints[2][1] * t * oneMinT * oneMinT;
tmp += newBezierPoints[3][1] * oneMinT * oneMinT * oneMinT;
tmp -= targetPoints[i][1];
tmp *= 6 * t * oneMinT;
dY1 += tmp * t;
dY2 += tmp * oneMinT;
}
dX1 /= GRADIENT_DESCENT_SAMPLE_COUNT;
dX2 /= GRADIENT_DESCENT_SAMPLE_COUNT;
dY1 /= GRADIENT_DESCENT_SAMPLE_COUNT;
dY2 /= GRADIENT_DESCENT_SAMPLE_COUNT;
newBezierPoints[1][0] -= LEARNING_RATE * dX1;
newBezierPoints[1][1] -= LEARNING_RATE * dY1;
newBezierPoints[2][0] -= LEARNING_RATE * dX2;
newBezierPoints[2][1] -= LEARNING_RATE * dY2;
}
private double[][] calculateMouseSamples(int fromIndex, int toIndex) {
double[][] mouseSamples = new double[GRADIENT_DESCENT_SAMPLE_COUNT][2];
double totExamplesLength = 0;
double[] lengthToPoints = new double[toIndex - fromIndex + 1];
lengthToPoints[0] = 0;
// find total length of painted lines
for (int i = fromIndex + 1; i <= toIndex; i++) {
totExamplesLength += this.dist(all_points[i][0], all_points[i][1], all_points[i - 1][0],
all_points[i - 1][1]);
lengthToPoints[i - fromIndex] = totExamplesLength;
}
if (totExamplesLength == 0) {
for (int i = 0; i < GRADIENT_DESCENT_SAMPLE_COUNT; i++) {
mouseSamples[i][0] = all_points[fromIndex][0];
mouseSamples[i][1] = all_points[fromIndex][1];
}
return mouseSamples;
}
int index = 0;
double factor;
for (int i = 0; i < GRADIENT_DESCENT_SAMPLE_COUNT; i++) {
double distFromFirst = (i + 1) * totExamplesLength / (GRADIENT_DESCENT_SAMPLE_COUNT + 1);
while (lengthToPoints[index] < distFromFirst)
index++;
factor = (distFromFirst - lengthToPoints[index - 1]) / (lengthToPoints[index] - lengthToPoints[index - 1]);
mouseSamples[i][0] = factor * (all_points[index + fromIndex][0] - all_points[index + fromIndex - 1][0])
+ all_points[index + fromIndex][0];
mouseSamples[i][1] = factor * (all_points[index + fromIndex][1] - all_points[index + fromIndex - 1][1])
+ all_points[index + fromIndex][1];
}
return mouseSamples;
}
private void adjustNewBezierEndPoint() {
// this.newBezierPoints[2][0] += all_points[nPoints - 1][0]
// - all_points[nPoints - 2][0];
// this.newBezierPoints[2][1] += all_points[nPoints - 1][1]
// - all_points[nPoints - 2][1];
this.newBezierPoints[0][0] = all_points[nPoints - 1][0];
this.newBezierPoints[0][1] = all_points[nPoints - 1][1];
}
private void insertPoint(double x, double y) {
if (x == all_points[nPoints - 1][0] && y == all_points[nPoints - 1][1])
return;
// dynamicly increase arraysize
if (this.nPoints >= all_points.length) {
double[][] tmp = new double[all_points.length + 5][2];
System.arraycopy(all_points, 0, tmp, 0, all_points.length);
all_points = tmp;
}
all_points[nPoints] = new double[] { x, y };
this.nPoints++;
}
/**
* for abort (ESC pressed for instance)
*
*/
public void abort() {
this.updateProfile = false;
this.isVisible = false;
}
public void paint(Graphics g, double magnification, Rectangle srcRect, boolean active) {
if (isVisible) {
Graphics2D g2d = (Graphics2D) g;
g2d.translate((profile.getX() - srcRect.x) * magnification, (profile.getY() - srcRect.y) * magnification);
// g2d.translate((- srcRect.x) * magnification,
// (- srcRect.y) * magnification);
g.setColor(Color.GREEN);
for (int i = lastBezierIndex + 1; i < nPoints; i++) {
g.drawLine((int) (all_points[i][0] * magnification), (int) (all_points[i][1] * magnification),
(int) (all_points[i - 1][0] * magnification), (int) (all_points[i - 1][1] * magnification));
}
// g.setColor(Color.RED);
// for (int i = 0; i < targetSamples.length; i++) {
// g.fillOval((int) (targetSamples[i][0] * magnification - 2),
// (int) (targetSamples[i][1] * magnification - 2), 5, 5);
// g.drawString("" + i,
// (int) (targetSamples[i][0] * magnification),
// (int) (targetSamples[i][1] * magnification));
// }
g.setColor(Color.BLUE);
double lastX;
double lastY;
for (int i = 1; i < nBeziers; i++) {
lastX = b_points[i][0];
lastY = b_points[i][1];
for (int j = 0; j <= 20; j++) {
double t = (double) j / 20;
double newX = b_points[i - 1][0] * t * t * t;
newX += 3 * r_points[i - 1][0] * t * t * (1 - t);
newX += 3 * l_points[i][0] * t * (1 - t) * (1 - t);
newX += b_points[i][0] * (1 - t) * (1 - t) * (1 - t);
double newY = b_points[i - 1][1] * t * t * t;
newY += 3 * r_points[i - 1][1] * t * t * (1 - t);
newY += 3 * l_points[i][1] * t * (1 - t) * (1 - t);
newY += b_points[i][1] * (1 - t) * (1 - t) * (1 - t);
g.drawLine((int) (lastX * magnification), (int) (lastY * magnification),
(int) (newX * magnification), (int) (newY * magnification));
lastX = newX;
lastY = newY;
}
}
// g.setColor(Color.GREEN);
// lastX = newBezierPoints[3][0];
// lastY = newBezierPoints[3][1];
// for (int i = 0; i <= 20; i++) {
// double t = (double) i / 20;
// double newX = newBezierPoints[0][0] * t * t * t;
// newX += 3 * newBezierPoints[1][0] * t * t * (1 - t);
// newX += 3 * newBezierPoints[2][0] * t * (1 - t) * (1 - t);
// newX += newBezierPoints[3][0] * (1 - t) * (1 - t) * (1 - t);
//
// double newY = newBezierPoints[0][1] * t * t * t;
// newY += 3 * newBezierPoints[1][1] * t * t * (1 - t);
// newY += 3 * newBezierPoints[2][1] * t * (1 - t) * (1 - t);
// newY += newBezierPoints[3][1] * (1 - t) * (1 - t) * (1 - t);
//
// g.drawLine((int) (lastX * magnification),
// (int) (lastY * magnification),
// (int) (newX * magnification),
// (int) (newY * magnification));
// lastX = newX;
// lastY = newY;
// }
g2d.translate(-(profile.getX() - srcRect.x) * magnification, -(profile.getY() - srcRect.y) * magnification);
// g2d.translate((srcRect.x) * magnification,
// ( srcRect.y) * magnification);
}
}
private double squaredDist(double x1, double y1, double x2, double y2) {
double dx = x1 - x2;
double dy = y1 - y2;
return dx * dx + dy * dy;
}
private double dist(double x1, double y1, double x2, double y2) {
double dx = x1 - x2;
double dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
public int getMouseX() {
return (int) mousePosition[0];
}
public int getMouseY() {
return (int) mousePosition[1];
}
}