void bicubicbezier2D_bbox(const Point *p0,const Point *p1, const Point *p2,const Point *p3, const PolyBBExtras *extra, Rectangle *rect) { double x[4],y[4]; Point vl,vt,p,tt; double *xy; int i,extr; double u[2]; rect->setLeft(p0->x()); rect->setRight(p0->x()); rect->setTop(p0->y()); rect->setBottom(p0->y()); rectangle_add_point(rect,p3); point_copy_add_scaled(&vl,p0,p1,-1); point_normalize(&vl); add_arrow_rectangle(rect,p0,&vl,extra->startLong, qMax(extra->startTrans, extra->middleTrans)); point_copy_add_scaled(&vl,p3,p2,-1); point_normalize(&vl); add_arrow_rectangle(rect,p3,&vl,extra->endLong, qMax(extra->endTrans, extra->middleTrans)); x[0] = p0->x(); x[1] = p1->x(); x[2] = p2->x(); x[3] = p3->x(); y[0] = p0->y(); y[1] = p1->y(); y[2] = p2->y(); y[3] = p3->y(); for (xy = x; xy ; xy=(xy==x?y:NULL) ) { extr = bicubicbezier_extrema(xy,u); for (i=0;i<extr;i++) { if ((u[i]<0) || (u[i]>1)) continue; p.setX(bezier_eval(x,u[i])); vl.setX(bezier_eval_tangent(x,u[i])); p.setY(bezier_eval(y,u[i])); vl.setY(bezier_eval_tangent(y,u[i])); point_normalize(&vl); point_get_perp(&vt,&vl); point_copy_add_scaled(&tt,&p,&vt,extra->middleTrans); rectangle_add_point(rect,&tt); point_copy_add_scaled(&tt,&p,&vt,-extra->middleTrans); rectangle_add_point(rect,&tt); } } }
/** Calculate the boundingbox for a 2D bezier curve segment. * @param p0 start point * @param p1 1st control point * @param p2 2nd control point * @param p3 end point * @param extra information about extra space from linewidth and arrow to add to the bounding box * @param rect The rectangle that the segment fits inside. */ void bicubicbezier2D_bbox(const Point *p0,const Point *p1, const Point *p2,const Point *p3, const PolyBBExtras *extra, Rectangle *rect) { real x[4],y[4]; Point vl,vt,p,tt; real *xy; int i,extr; real u[2]; rect->left = rect->right = p0->x; rect->top = rect->bottom = p0->y; rectangle_add_point(rect,p3); /* start point */ point_copy_add_scaled(&vl,p0,p1,-1); point_normalize(&vl); add_arrow_rectangle(rect,p0,&vl,extra->start_long,MAX(extra->start_trans, extra->middle_trans)); /* end point */ point_copy_add_scaled(&vl,p3,p2,-1); point_normalize(&vl); add_arrow_rectangle(rect,p3,&vl,extra->end_long,MAX(extra->end_trans, extra->middle_trans)); /* middle part */ x[0] = p0->x; x[1] = p1->x; x[2] = p2->x; x[3] = p3->x; y[0] = p0->y; y[1] = p1->y; y[2] = p2->y; y[3] = p3->y; for (xy = x; xy ; xy=(xy==x?y:NULL) ) { /* sorry */ extr = bicubicbezier_extrema(xy,u); for (i=0;i<extr;i++) { if ((u[i]<0) || (u[i]>1)) continue; p.x = bezier_eval(x,u[i]); vl.x = bezier_eval_tangent(x,u[i]); p.y = bezier_eval(y,u[i]); vl.y = bezier_eval_tangent(y,u[i]); point_normalize(&vl); point_get_perp(&vt,&vl); point_copy_add_scaled(&tt,&p,&vt,extra->middle_trans); rectangle_add_point(rect,&tt); point_copy_add_scaled(&tt,&p,&vt,-extra->middle_trans); rectangle_add_point(rect,&tt); } } }
static Point bezier_line_eval(BezPoint *line,int p,real u) { real bx[4],by[4]; Point res; bx[0]=line[p-1].p3.x; bx[1]=line[p].p1.x; bx[2]=line[p].p2.x; bx[3]=line[p].p3.x; by[0]=line[p-1].p3.y; by[1]=line[p].p1.y; by[2]=line[p].p2.y; by[3]=line[p].p3.y; res.x=bezier_eval(bx,u); res.y=bezier_eval(by,u); return res; }
/* compute bezier for Dependency */ static void compute_dependency(BezPoint *line, BezPoint *bpl) { Point ref; double dx,dy,dxp,dyp,k; real bx[4],by[4]; /* computing anchor point and tangent */ bx[0]=line[1].p3.x; bx[1]=line[2].p1.x; bx[2]=line[2].p2.x; bx[3]=line[2].p3.x; by[0]=line[1].p3.y; by[1]=line[2].p1.y; by[2]=line[2].p2.y; by[3]=line[2].p3.y; ref.x=bezier_eval(bx,0.25); ref.y=bezier_eval(by,0.25); dx=bezier_eval_tangent(bx,0.25); dy=bezier_eval_tangent(by,0.25); k=sqrt(dx*dx+dy*dy); /* normalizing */ if (k!=0) { dx=dx/k; dy=dy/k; dxp=dy; dyp=-dx; } else { dx=0; dy=1; dxp=1; dyp=0; } /* more offset for origin */ ref.x -= LINK_DEP_HEIGHT * dx; ref.y -= LINK_DEP_HEIGHT * dy; /* bezier */ bpl[0].type=BEZ_MOVE_TO; bpl[0].p1.x = ref.x + LINK_DEP_WIDTH/2.0 * dxp; bpl[0].p1.y = ref.y + LINK_DEP_WIDTH/2.0 * dyp; bpl[1].type=BEZ_CURVE_TO; bpl[1].p3.x = ref.x + LINK_DEP_HEIGHT * dx; bpl[1].p3.y = ref.y + LINK_DEP_HEIGHT * dy; bpl[1].p1.x = ref.x + LINK_DEP_WIDTH/2.0 * dxp + LINK_DEP_HEIGHT * dx; bpl[1].p1.y = ref.y + LINK_DEP_WIDTH/2.0 * dyp + LINK_DEP_HEIGHT * dy; bpl[1].p2.x = bpl[1].p1.x; bpl[1].p2.y = bpl[1].p1.y; bpl[2].type=BEZ_CURVE_TO; bpl[2].p3.x = ref.x - LINK_DEP_WIDTH/2.0 * dxp; bpl[2].p3.y = ref.y - LINK_DEP_WIDTH/2.0 * dyp; bpl[2].p1.x = ref.x - LINK_DEP_WIDTH/2.0 * dxp + LINK_DEP_HEIGHT * dx; bpl[2].p1.y = ref.y - LINK_DEP_WIDTH/2.0 * dyp + LINK_DEP_HEIGHT * dy; bpl[2].p2.x = bpl[2].p1.x; bpl[2].p2.y = bpl[2].p1.y; bpl[3].type=BEZ_LINE_TO; bpl[3].p1.x=bpl[0].p1.x; bpl[3].p1.y=bpl[0].p1.y; }