%% options copyright owner = Dirk Krause copyright year = 2012-2014 license = bsd %% header #ifdef __cplusplus extern "C" { #endif /** Bezier curve value calculation. @param x0 Start point value. @param xp Value in control point near start. @param xm Value in control point near end. @param x1 End point. @param t The t parameter. @param ec Pointer to error code variable, may be NULL. @return Calculation result. */ double dk3bezier_value( double x0, double xp, double xm, double x1, double t, int *ec ); /** Add Bezier curve segment to bounding box. @param bb Bounding box to modify. @param x0 Start point x coordinate. @param y0 Start point y coordinate. @param xp Control point near start x coordinate. @param yp Control point near start y coordinate. @param xm Control point near end x coordinate. @param ym Control point near end y coordinate. @param x1 End point x coordinate. @param y1 End point y coordinate. @param ra Half line width. @param ec Pointer to error code variable, may be NULL. @return 1 on success, 0 on error. */ int dk3bezier_bb( dk3_bb_t *bb, double x0, double y0, double xp, double yp, double xm, double ym, double x1, double y1, double ra, int *ec ); #ifdef __cplusplus } #endif %% module #include "dk3all.h" #include "dk3bb.h" #include "dk3bezcu.h" $!trace-include double dk3bezier_value( double x0, double xp, double xm, double x1, double t, int *ec ) { int mec = 0; double back; $? "+ dk3bezier_value %lg %lg %lg %lg %lg", x0, xp, xm, x1, t back = dk3ma_d_add_ok( x0, dk3ma_d_mul_ok( t, dk3ma_d_add_ok( dk3ma_d_sub_ok( dk3ma_d_mul_ok(3.0, xp, &mec), dk3ma_d_mul_ok(3.0, x0, &mec), &mec ), dk3ma_d_mul_ok( t, dk3ma_d_add_ok( dk3ma_d_add_ok( dk3ma_d_sub_ok( dk3ma_d_mul_ok(3.0, xm, &mec), dk3ma_d_mul_ok(6.0, xp, &mec), &mec ), dk3ma_d_mul_ok(3.0, x0, &mec), &mec ), dk3ma_d_mul_ok( t, dk3ma_d_add_ok( dk3ma_d_sub_ok( dk3ma_d_mul_ok(3.0, xp, &mec), dk3ma_d_mul_ok(3.0, xm, &mec), &mec ), dk3ma_d_sub_ok(x1, x0, &mec), &mec ), &mec ), &mec ), &mec ), &mec ), &mec ), &mec ); $? ". mec = %d", mec if(mec) { if(ec) { *ec = mec; } } $? "- dk3bezier_value %lg", back return back; } /** Apply one t value to a bounding box. @param bb Bounding box to modify. @param x0 Start value. @param xp Control value for start. @param xm Control value for end. @param x1 End value. @param ra Point radius (half line width). @param tv The t value. @param isy Flag: Y direction. @param ec Pointer to error code variable, may be NULL. @return 1 on success, 0 on error. */ static int dk3bezier_t_dimension( dk3_bb_t *bb, double x0, double xp, double xm, double x1, double ra, double tv, int isy, int *ec ) { double val; int back = 1; int mec = 0; $? "+ dk3bezier_t_dimension %lg %lg %lg %lg y=%d", x0, xp, xm, x1, isy if(tv > 0.0) { if(tv < 1.0) { val = dk3bezier_value(x0, xp, xm, x1, tv, &mec); $? ". mec = %d", mec if(isy) { if(!dk3bb_add_y_width(bb, val, ra)) { back = 0; } } else { if(!dk3bb_add_x_width(bb, val, ra)) { back = 0; } } } } if(mec) { $? "! mec" back = 0; if(ec) { *ec = mec; } } $? "- dk3bezier_t_dimension %d", back return back; } #if VERSION_BEFORE_20121218 /** Apply one dimension to a bounding box. @param bb Bounding box to modify. @param x0 Start value. @param xp Control value for start. @param xm Control value for end. @param x1 End value. @param ra Point radius (half line width). @param isy Flag: Y direction. @param ec Pointer to error code variable, may be NULL. @return 1 on success, 0 on error. */ static int dk3bezier_bb_dimension( dk3_bb_t *bb, double x0, double xp, double xm, double x1, double ra, int isy, int *ec ) { double n; double z1; double z2; double t; int back = 1; int mec = 0; $? "+ dk3bezier_bb_dimension %lg %lg %lg %lg y=%d", x0, xp, xm, x1, isy n = dk3ma_d_add_ok( dk3ma_d_sub_ok(x1, x0, &mec), dk3ma_d_mul_ok(3.0, dk3ma_d_sub_ok(xp, xm, &mec), &mec), &mec ); $? ". mec = %d", mec z1 = dk3ma_d_sub_ok( dk3ma_d_sub_ok(dk3ma_d_mul_ok(2.0, xp, &mec), xm, &mec), x0, &mec ); $? ". mec = %d", mec z2 = dk3ma_d_add_ok( dk3ma_d_sub_ok( xm, dk3ma_d_mul_ok(2.0, xp, &mec), &mec ), x0, &mec ); $? ". mec = %d", mec z2 = dk3ma_d_mul_ok(z2, z2, &mec); z2 = dk3ma_d_sub_ok( z2, dk3ma_d_mul_ok( dk3ma_d_sub_ok(xp, x0, &mec), n, &mec ), &mec ); $? ". mec = %d", mec if(z2 >= 0.0) { z2 = sqrt(z2); $? ". z1 = %lg z2 = %lg", z1, z2 t = dk3ma_d_div_ok( dk3ma_d_add_ok(z1, z2, &mec), n, &mec ); $? ". mec = %d", mec if(!dk3bezier_t_dimension(bb, x0, xp, xm, x1, ra, t, isy, &mec)) { back = 0; } $? ". mec = %d", mec t = dk3ma_d_div_ok( dk3ma_d_sub_ok(z1, z2, &mec), n, &mec ); $? ". mec = %d", mec if(!dk3bezier_t_dimension(bb, x0, xp, xm, x1, ra, t, isy, &mec)) { back = 0; } $? ". mec = %d", mec } if(mec) { $? "! math error" back = 0; if(ec) { *ec = mec; } } $? "- dk3bezier_bb_dimension %d", back return back; } #else /** Apply one dimension to a bounding box. @param bb Bounding box to modify. @param x0 Start value. @param xp Control value for start. @param xm Control value for end. @param x1 End value. @param ra Point radius (half line width). @param isy Flag: Y direction. @param ec Pointer to error code variable, may be NULL. @return 1 on success, 0 on error. */ static int dk3bezier_bb_dimension( dk3_bb_t *bb, double x0, double xp, double xm, double x1, double ra, int isy, int *ec ) { double n; double z1; double z2; double t; int back = 1; int mec = 0; int testmec; $? "+ dk3bezier_bb_dimension %lg %lg %lg %lg y=%d", x0, xp, xm, x1, isy n = dk3ma_d_add_ok( dk3ma_d_sub_ok(x1, x0, &mec), dk3ma_d_mul_ok(3.0, dk3ma_d_sub_ok(xp, xm, &mec), &mec), &mec ); $? ". mec = %d", mec z1 = dk3ma_d_sub_ok( dk3ma_d_sub_ok(dk3ma_d_mul_ok(2.0, xp, &mec), xm, &mec), x0, &mec ); $? ". mec = %d", mec z2 = dk3ma_d_add_ok( dk3ma_d_sub_ok( xm, dk3ma_d_mul_ok(2.0, xp, &mec), &mec ), x0, &mec ); $? ". mec = %d", mec z2 = dk3ma_d_mul_ok(z2, z2, &mec); z2 = dk3ma_d_sub_ok( z2, dk3ma_d_mul_ok( dk3ma_d_sub_ok(xp, x0, &mec), n, &mec ), &mec ); $? ". mec = %d", mec if(z2 >= 0.0) { z2 = sqrt(z2); $? ". z1 = %lg z2 = %lg", z1, z2 testmec = 0; t = dk3ma_d_div_ok( dk3ma_d_add_ok(z1, z2, &mec), n, &testmec ); $? ". mec = %d", mec if(0 == testmec) { if(!dk3bezier_t_dimension(bb, x0, xp, xm, x1, ra, t, isy, &mec)) { back = 0; } $? ". mec = %d", mec } testmec = 0; t = dk3ma_d_div_ok( dk3ma_d_sub_ok(z1, z2, &mec), n, &testmec ); $? ". mec = %d", mec if(0 == testmec) { if(!dk3bezier_t_dimension(bb, x0, xp, xm, x1, ra, t, isy, &mec)) { back = 0; } $? ". mec = %d", mec } } if(mec) { $? "! math error" back = 0; if(ec) { *ec = mec; } } $? "- dk3bezier_bb_dimension %d", back return back; } #endif int dk3bezier_bb( dk3_bb_t *bb, double x0, double y0, double xp, double yp, double xm, double ym, double x1, double y1, double ra, int *ec ) { int back = 0; int mec = 0; $? "+ dk3bezier_bb %lg %lg %lg %lg %lg %lg %lg %lg", x0, y0, xp, yp, xm, ym, x1, y1 if(bb) { back = 1; if(!dk3bb_point_width(bb, x0, y0, ra)) { back = 0; } if(!dk3bb_point_width(bb, x1, y1, ra)) { back = 0; } if(!dk3bezier_bb_dimension(bb, x0, xp, xm, x1, ra, 0, &mec)) { back = 0; } if(!dk3bezier_bb_dimension(bb, y0, yp, ym, y1, ra, 1, &mec)) { back = 0; } if(mec) { back = 0; if(ec) { *ec = mec; } } } else { if(ec) { *ec = DK3_ERROR_INVALID_ARGS; } } $? "- dk3bezier_bb %d", back return back; }