void initCurveSegment(float x, float y, CurveSegment seg) { seg.C0 = new Point(x, y); seg.C1 = new Point(x, y); seg.C2 = new Point(x, y); seg.C3 = new Point(x, y); }
void resetControlVertices(CurveSegment seg) { if (seg.save != null) { seg.C1 = seg.save.C1; seg.C2 = seg.save.C2; seg.C3 = seg.save.C3; } }
void drawCurve(CurveSegment seg, bool noClear) { if (!noClear) { o.Clear(); } o.BezierCurve(seg); }
void saveControlVertices(CurveSegment seg) { if (seg.save == null) { seg.save = new CurveSegment(); } seg.save.C1 = seg.C1; seg.save.C2 = seg.C2; seg.save.C3 = seg.C3; }
public bool testCorner(float x, float y, CurveSegment seg) { float angle = getVectorAngle(new Point(seg.C2.x - seg.C3.x, seg.C2.y - seg.C3.y), new Point(x - seg.C3.x, y - seg.C3.y)); if (angle < MAX_ANGLE) { return(true); } else { return(false); } }
public void mouseUpCallback() { CurveSegment currentSeg = curve.curveSeg[curve.curveSeg.Count - 1]; //drawAllCurves(o, curve, o.pctx); //o.pctx.clearRect(0, 0, o.c.width(), o.c.height()); o.Clear(); o.BezierCurve(currentSeg); /*o.pctx.clearRect (0, 0, o.c.width(), o.c.height()); * o.pctx.lineWidth = 3; * o.pctx.moveTo(currentSeg.C0.x, currentSeg.C0.y); * o.pctx.bezierCurveTo(currentSeg.C1.x, currentSeg.C1.y, * currentSeg.C2.x, currentSeg.C2.y, * currentSeg.C3.x, currentSeg.C3.y); * o.pctx.stroke();*/ }
Point calc(CurveSegment seg, float t) { float x, y; //t = Math.pow(t, 1 / 2); x = seg.C0.x * (1 - t) * (1 - t) * (1 - t) + 3 * seg.C1.x * t * (1 - t) * (1 - t) + 3 * seg.C2.x * t * t * (1 - t) + seg.C3.x * t * t * t; y = seg.C0.y * (1 - t) * (1 - t) * (1 - t) + 3 * seg.C1.y * t * (1 - t) * (1 - t) + 3 * seg.C2.y * t * t * (1 - t) + seg.C3.y * t * t * t; return(new Point(x, y)); }
public void BezierCurve(CurveSegment seg) { DrawLine(seg.C0, seg.C1); DrawLine(seg.C1, seg.C2); DrawLine(seg.C2, seg.C3); }
public CurveSegment mouseMoveCallback(float x, float y) { CurveSegment currentSeg = curve.curveSeg [curve.curveSeg.Count - 1]; Point prev = new Point(currentSeg.C3); string updateResult; CurveSegment nextSeg; updateResult = updateCurveSegment(x, y, currentSeg); for (int i = 0; i < curve.curveSeg.Count - 1; i++) { o.BezierCurve(curve.curveSeg [i]); } if (updateResult != "SUCCESS") { nextSeg = new CurveSegment(); initCurveSegment(prev.x, prev.y, nextSeg); clearRaster(rasterBorder, vectorDistMap, o); o.Clear(); o.BezierCurve(currentSeg); /*o.pctx.clearRect (0, 0, o.c.width(), o.c.height()); * o.pctx.lineWidth = 3; * o.pctx.moveTo(currentSeg.C0.x, currentSeg.C0.y); * o.pctx.bezierCurveTo(currentSeg.C1.x, currentSeg.C1.y, * currentSeg.C2.x, currentSeg.C2.y, * currentSeg.C3.x, currentSeg.C3.y); * o.pctx.stroke();*/ if (updateResult == "FAILURE") { nextSeg.constrained = true; nextSeg.tan = new Point(currentSeg.C3.x - currentSeg.C2.x, currentSeg.C3.y - currentSeg.C2.y); nextSeg.tan.normalize(); nextSeg.C2.x = nextSeg.C0.x - nextSeg.tan.x; nextSeg.C2.y = nextSeg.C0.y - nextSeg.tan.y; } else { if (updateResult != "CORNER") { nextSeg.constrained = false; } } updateCurveSegment(x, y, nextSeg); curve.curveSeg.Add(nextSeg); } /* * o.ctx.clearRect (0, 0, o.c.width(), o.c.height()); * o.ctx.moveTo(currentSeg.C0.x, currentSeg.C0.y); * o.ctx.bezierCurveTo(currentSeg.C1.x, currentSeg.C1.y, * currentSeg.C2.x, currentSeg.C2.y, * currentSeg.C3.x, currentSeg.C3.y); * o.ctx.stroke();*/ return(currentSeg); }
string updateCurveSegment(float x, float y, CurveSegment seg) { Point prev = new Point(seg.C3); float error = 0; int nIteration = 0; Point f1, f2; int i, max_i; Point p = new Point(), dp = new Point(); float d; float projection = 0; Point v = new Point((seg.C3.x - seg.C0.x) / 3, (seg.C3.y - seg.C0.y) / 3); if (testCorner(x, y, seg)) { return("CORNER"); } saveControlVertices(seg); seg.C3 = new Point(x, y); seg.C2 = new Point(seg.C2.x + (x - prev.x), seg.C2.y + (y - prev.y)); if (v.getLength() < LINE_D) { seg.C2.x = seg.C3.x - v.x; seg.C2.y = seg.C3.y - v.y; if (seg.constrained == true) { projection = seg.tan.getScalarMult(v); v = new Point(projection * seg.tan.x, projection * seg.tan.y); } seg.C1.x = seg.C0.x + v.x; seg.C1.y = seg.C0.y + v.y; } renderLineCell(prev.x, prev.y, x, y, BOX_SIZE, vectorDistMap); renderPointCell(prev.x, prev.y, BOX_SIZE, vectorDistMap); //drawCurve(o, seg); do { f1 = new Point(); f2 = new Point(); error = 0; for (i = 0, max_i = N; i < max_i; i += 1) { p = calc(seg, ti[i]); dp = interpVectorDist(vectorDistMap, p.x, p.y); d = dp.getLength(); if (d > error) { error = d; } error += d; f1.x += 6 * ti[i] * (1 - ti[i]) * (1 - ti[i]) * d * dp.x / N; f1.y += 6 * ti[i] * (1 - ti[i]) * (1 - ti[i]) * d * dp.y / N; f2.x += 6 * ti[i] * ti[i] * (1 - ti[i]) * d * dp.x / N; f2.y += 6 * ti[i] * ti[i] * (1 - ti[i]) * d * dp.y / N; } error /= N; if (seg.constrained == true) { projection = seg.tan.getScalarMult(f1); f1 = new Point(projection * seg.tan.x, projection * seg.tan.y); } seg.C1.x = seg.C1.x - INCREASE_K * f1.x; seg.C1.y = seg.C1.y - INCREASE_K * f1.y; seg.C2.x = seg.C2.x - INCREASE_K * f2.x; seg.C2.y = seg.C2.y - INCREASE_K * f2.y; drawCurve(seg, false); nIteration++; } while ((nIteration < MAX_N_ITERATION)); /* * if (breakFlag) { * breakFlag = false; * resetControlVertices(seg); * return 'FAILURE'; * } * drawCurve(o, seg); * breakFlag = false; * return 'SUCCESS';*/ if (error < MAX_ERROR) { drawCurve(seg, false); return("SUCCESS"); } else { resetControlVertices(seg); return("FAILURE"); } }