Beispiel #1
0
static void CalcBSpline(
    IntCoord cminus1x, IntCoord cminus1y, IntCoord cx, IntCoord cy,
    IntCoord cplus1x, IntCoord cplus1y, IntCoord cplus2x, IntCoord cplus2y
) {
    double p0x, p1x, p2x, p3x, tempx,
	   p0y, p1y, p2y, p3y, tempy;
    
    ThirdPoint(
        double(cx), double(cy), double(cplus1x), double(cplus1y), p1x, p1y
    );
    ThirdPoint(
        double(cplus1x), double(cplus1y), double(cx), double(cy), p2x, p2y
    );
    ThirdPoint(
        double(cx), double(cy), double(cminus1x), double(cminus1y),
	tempx, tempy
    );
    Midpoint(tempx, tempy, p1x, p1y, p0x, p0y);
    ThirdPoint(
        double(cplus1x), double(cplus1y), double(cplus2x), double(cplus2y),
	tempx, tempy
    );
    Midpoint(tempx, tempy, p2x, p2y, p3x, p3y);
    
    AddBezierCurve(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y);
}
Beispiel #2
0
void Painter::Curve(
    Canvas* c, IntCoord x0, IntCoord y0, IntCoord x1, IntCoord y1,
    IntCoord x2, IntCoord y2, IntCoord x3, IntCoord y3
) {
    IntCoord tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3;
    
    llcount = 0;
    Map(c, x0, y0, tx0, ty0);
    Map(c, x1, y1, tx1, ty1);
    Map(c, x2, y2, tx2, ty2);
    Map(c, x3, y3, tx3, ty3);
    AddBezierCurve(tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3);
    MultiLineNoMap(c, llx, lly, llcount);
}
Beispiel #3
0
static void AddBezierCurve(
    double x0, double y0, double x1, double y1,
    double x2, double y2, double x3, double y3
) {
    double midx01, midx12, midx23, midlsegx, midrsegx, cx;
    double midy01, midy12, midy23, midlsegy, midrsegy, cy;
    
    Midpoint(x0, y0, x1, y1, midx01, midy01);
    Midpoint(x1, y1, x2, y2, midx12, midy12);
    Midpoint(x2, y2, x3, y3, midx23, midy23);
    Midpoint(midx01, midy01, midx12, midy12, midlsegx, midlsegy);
    Midpoint(midx12, midy12, midx23, midy23, midrsegx, midrsegy);
    Midpoint(midlsegx, midlsegy, midrsegx, midrsegy, cx, cy);    

    if (CanApproxWithLine(x0, y0, midlsegx, midlsegy, cx, cy)) {
        AddLine(x0, y0, cx, cy);
    } else if (
        (midx01 != x1) || (midy01 != y1) ||
	(midlsegx != x2) || (midlsegy != y2) ||
	(cx != x3) || (cy != y3)
    ) {    
        AddBezierCurve(
	    x0, y0, midx01, midy01, midlsegx, midlsegy, cx, cy
	);
    }
    if (CanApproxWithLine(cx, cy, midx23, midy23, x3, y3)) {
        AddLine(cx, cy, x3, y3);
    } else if (
        (cx != x0) || (cy != y0) ||
	(midrsegx != x1) || (midrsegy != y1) ||
	(midx23 != x2) || (midy23 != y2)
    ) {        
        AddBezierCurve(
	    cx, cy, midrsegx, midrsegy, midx23, midy23, x3, y3
	);
    }
}
Beispiel #4
0
/*
*  FitCubic :
*  	Fit a Bezier curve to a (sub)set of digitized points
*/
void CBCStroke::FitCubic(
DISCURVE& d,			/*  Array of digitized points */
int		first,int last,/* Indices of first and last pts in region */
Vector2	tHat1,Vector2 tHat2,	/* Unit tangent vectors at endpoints */
double	error)		/*  User-defined error squared	   */
{
	BezierCurve	bezCurve; /*Control points of fitted Bezier curve*/
	double	*u;		/*  Parameter values for point  */
	double	*uPrime;	/*  Improved parameter values */
	double	maxError;	/*  Maximum fitting error	 */
	int		splitPoint;	/*  Point to split point set at	 */
	int		nPts;		/*  Number of points in subset  */
	double	iterationError; /*Error below which you try iterating  */
	int		maxIterations = 5; /*  Max times to try iterating  */
	Vector2	tHatCenter;   	/* Unit tangent vector at splitPoint */
	int		i;		

	iterationError = error * error;
	nPts = last - first + 1;

	/*  Use heuristic if region only has two points in it */
	if (nPts == 2) {
		double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;

		bezCurve = (Point2 *)malloc(4 * sizeof(Point2));
		bezCurve[0] = d[first];
		bezCurve[3] = d[last];
		V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
		V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
		//DrawBezierCurve(, bezCurve);
		double u[2];
		u[0]=0;
		u[1]=1;
		PARAMERLIST paramList;
		CopyParamList(first,last,u,paramList);
		AddBezierCurve(3,bezCurve,paramList);

		free((void *)bezCurve);
		return;
	}

	/*  Parameterize points, and attempt to fit curve */
	u = ChordLengthParameterize(d, first, last);
	bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);

	/*  Find max deviation of points to fitted curve */
	maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
	if (maxError < error) {
		//DrawBezierCurve(3, bezCurve);
		PARAMERLIST paramList;
		CopyParamList(first,last,u,paramList);
		AddBezierCurve(3,bezCurve,paramList);
		free((void *)u);
		free((void *)bezCurve);
		return;
	}


	/*  If error not too large, try some reparameterization  */
	/*  and iteration */
	if (maxError < iterationError) {
		for (i = 0; i < maxIterations; i++) {
			uPrime = Reparameterize(d, first, last, u, bezCurve);
			bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
			maxError = ComputeMaxError(d, first, last,
				bezCurve, uPrime, &splitPoint);
			if (maxError < error) {
				//DrawBezierCurve(3, bezCurve);
				PARAMERLIST paramList;
				CopyParamList(first,last,u,paramList);
				AddBezierCurve(3,bezCurve,paramList);

				free((void *)u);
				free((void *)bezCurve);
				return;
			}
			free((void *)u);
			u = uPrime;
		}
	}

	/* Fitting failed -- split at max error point and fit recursively */
	free((void *)u);
	free((void *)bezCurve);
	tHatCenter = ComputeCenterTangent(d, splitPoint);
	FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
	V2Negate(&tHatCenter);
	FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
}