CubicSpline::CubicSpline(vector<Vector3> controlPoints, float tightness, int subDivisions) : m_length(0.f) { Vector3 endTangent; for (int i = 0; i < controlPoints.size()-1; i++) { vector<Vector3> path; Vector3 start = controlPoints[i]; Vector3 end = controlPoints[i+1]; path.push_back(start); if (endTangent != Vector3::Zero) { // start tangent becomes the negative of the previous end tangent path.push_back(-endTangent + start); } if (i < controlPoints.size() - 2) { Vector3 next = controlPoints[i + 2]; Vector3 line1 = start - end; Vector3 line2 = end - next; line1.Normalize(); line2.Normalize(); // average the two vectors to get the normal of reflection endTangent = Vector3((line1.x + line2.x) / 2.f, (line1.y + line2.y) / 2.f, (line1.z + line2.z) / 2.f); //endTangent.Normalize(); endTangent *= tightness; path.push_back(endTangent + end); } path.push_back(end); Bezier bezier = Bezier(path); float length = bezier.Length(subDivisions); m_length += length; m_bezierSections.push_back(std::make_pair(Bezier(bezier), length)); } }
void draw_surface(float width, float height) { /* pseudo 1. calculate p3-p2 2. set new bezier p0 = old bezier p3 3. new beier p1 = p0 + old(p3-p2)*/ Bezier tl = Bezier(width, height, angle); Vector4 d1 = tl.p3 - tl.p2; Vector4 d2 = tl.p7 - tl.p6; Vector4 d3 = tl.p11 - tl.p10; Vector4 d4 = tl.p15 - tl.p14; Vector4 g1 = tl.p3 + d1; Vector4 g2 = tl.p7 + d2; Vector4 g3 = tl.p11 + d3; Vector4 g4 = tl.p15 + d4; cout << "tlp7: " << tl.p7.y << endl; Bezier tr = Bezier(tl.p3, g1, tl.p7, g2, tl.p11, g3, tl.p15, g4, angle); //cout << "p0: " << tr.p0.y << " p3: " << tr.p3.y << " p12: " << tr.p12.y << " p15: " << tr.p15.y << endl; cout << "p4: " << tr.p4.y << " p8: " << tr.p8.y << " p7: " << tr.p7.y << " p11: " << tr.p11.y << endl; cout << "p5: " << tr.p5.y << endl; for (float t1 = -0.5; t1 < 0.49; t1 += 0.01) { for (float t2 = -0.5; t2 < 0.49; t2 += 0.01) { glColor3f(1, 0, 0); tl.tessellate(t1, t2, .1); glColor3f(0, 0, 1); tr.tessellate(t1, t2, .1); } } }
void Polygon::Bezier(QImage *backBuffer, double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, QColor color){ double m_distance_tolerance = 0.25; double x12 = (x1 + x2) / 2; double y12 = (y1 + y2) / 2; double x23 = (x2 + x3) / 2; double y23 = (y2 + y3) / 2; double x34 = (x3 + x4) / 2; double y34 = (y3 + y4) / 2; double x123 = (x12 + x23) / 2; double y123 = (y12 + y23) / 2; double x234 = (x23 + x34) / 2; double y234 = (y23 + y34) / 2; double x1234 = (x123 + x234) / 2; double y1234 = (y123 + y234) / 2; double dx = x4 - x1; double dy = y4-y1; double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx)); double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx)); if( (d2 + d3)*(d2 + d3) < m_distance_tolerance * (dx*dx + dy*dy) ){ drawLine(backBuffer, x1, y1, x4, y4, color); } else{ Bezier(backBuffer, x1, y1, x12, y12, x123, y123, x1234, y1234, color); Bezier(backBuffer, x1234, y1234, x234, y234, x34, y34, x4, y4, color); } }
double Measurement::NearestPointOnCurve(QPointF P, vector<QPointF> V) { QPointF *w; /* Ctl pts for 5th-degree eqn */ double t_candidate[W_DEGREE]; /* Possible roots */ int n_solutions; /* Number of roots found */ double t; /* Parameter value of closest pt*/ QPointF v_arr[4]; for(int i=0; i<4; i++) v_arr[i]=V[i]; /* Convert problem to 5th-degree Bezier form */ w = ConvertToBezierForm(P, v_arr); /* Find all possible roots of 5th-degree equation */ n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0); free((char *)w); /* Compare distances of P to all candidates, and to t=0, and t=1 */ { double dist, new_dist; QPointF p; QPointF v; int i; /* Check distance to beginning of curve, where t = 0 */ dist = V2SquaredLength(V2Sub(&P, &v_arr[0], &v)); t = 0.0; /* Find distances for candidate points */ for (i = 0; i < n_solutions; i++) { p = Bezier(v_arr, DEGREE, t_candidate[i], (QPointF *)NULL, (QPointF *)NULL); new_dist = V2SquaredLength(V2Sub(&P, &p, &v)); if (new_dist < dist) { dist = new_dist; t = t_candidate[i]; } } /* Finally, look at distance to end point, where t = 1.0 */ new_dist = V2SquaredLength(V2Sub(&P, &V[DEGREE], &v)); if (new_dist < dist) { dist = new_dist; t = 1.0; } } /* Return the point on the curve at parameter value t */ // printf("t : %4.12f\n", t); QPointF b=Bezier(v_arr, DEGREE, t, (QPointF *)NULL, (QPointF *)NULL); return V2DistanceBetween2Points(&P,&b); }
Point Bezier2D(Point p[4][4],float u,float v) { float U = 1-u; float V = 1-v; Point P; P.x = Bezier(x); P.y = Bezier(y); P.z = Bezier(z); return P; }
void setUpCurve(float d) { blc = Vector3(-d, 0, -d); brc = Vector3(d, 0, -d); trc = Vector3(d, 0, d); tlc = Vector3(-d, 0, d); float dist = d / 3; if (cp == 1) { glColor3f(1, 0, 1); Matrix4 tc; Matrix4 t; t.makeTranslate(blc.x, blc.y, blc.z); tc = objCamera.c; tc = tc*t; tc.transpose(); glLoadMatrixd(tc.getPointer()); glutWireSphere(.5, 20, 20); t.makeTranslate(brc.x, brc.y, brc.z); tc = objCamera.c; tc = tc*t; tc.transpose(); glLoadMatrixd(tc.getPointer()); glutWireSphere(.5, 20, 20); t.makeTranslate(trc.x, trc.y, trc.z); tc = objCamera.c; tc = tc*t; tc.transpose(); glLoadMatrixd(tc.getPointer()); glutWireSphere(.5, 20, 20); t.makeTranslate(tlc.x, tlc.y, tlc.z); tc = objCamera.c; tc = tc*t; tc.transpose(); glLoadMatrixd(tc.getPointer()); glutWireSphere(.5, 20, 20); } glColor3f(0, 0, 1); x1 = Bezier(blc, Vector3(-dist, 0, -1.5*d), Vector3(dist, 0, -1.5*d), brc); glColor3f(1, 1, 0); x2 = Bezier(brc, Vector3(d*1.5, 0, -dist), Vector3(d*1.5, 0, dist), trc); glColor3f(1, 0, 0); x3 = Bezier(trc, Vector3(dist, 0, 1.5*d), Vector3(-dist, 0, 1.5*d), tlc); glColor3f(1, 1, 1); x4 = Bezier(tlc, Vector3(-1.5*d, 0, dist), Vector3(-1.5*d, 0, -dist), blc); }
/* findHorizontal: * Given 4 Bezier control points pts, corresponding to the portion * of an initial spline with path parameter in the range * 0.0 <= tmin <= t <= tmax <= 1.0, return t where the spline * first crosses a horizontal line segment * [(xmin,ycoord),(xmax,ycoord)]. Return -1 if not found. * This is done by binary subdivision. */ static double findHorizontal(pointf * pts, double tmin, double tmax, double ycoord, double xmin, double xmax) { pointf Left[4]; pointf Right[4]; double t; int no_cross = countHorzCross(pts, ycoord); if (no_cross == 0) return -1.0; /* if 1 crossing and on the line y == ycoord (within 1 point) */ if ((no_cross == 1) && (ROUND(pts[3].y) == ROUND(ycoord))) { if ((xmin <= pts[3].x) && (pts[3].x <= xmax)) { return tmax; } else return -1.0; } /* split the Bezier into halves, trying the first half first. */ Bezier(pts, 3, 0.5, Left, Right); t = findHorizontal(Left, tmin, (tmin + tmax) / 2.0, ycoord, xmin, xmax); if (t >= 0.0) return t; return findHorizontal(Right, (tmin + tmax) / 2.0, tmax, ycoord, xmin, xmax); }
/* findVertical: * Given 4 Bezier control points pts, corresponding to the portion * of an initial spline with path parameter in the range * 0.0 <= tmin <= t <= tmax <= 1.0, return t where the spline * first crosses a vertical line segment * [(xcoord,ymin),(xcoord,ymax)]. Return -1 if not found. * This is done by binary subdivision. */ static double findVertical(pointf * pts, double tmin, double tmax, double xcoord, double ymin, double ymax) { pointf Left[4]; pointf Right[4]; double t; int no_cross = countVertCross(pts, xcoord); if (no_cross == 0) return -1.0; /* if 1 crossing and on the line x == xcoord (within 1 point) */ if ((no_cross == 1) && (ROUND(pts[3].x) == ROUND(xcoord))) { if ((ymin <= pts[3].y) && (pts[3].y <= ymax)) { return tmax; } else return -1.0; } /* split the Bezier into halves, trying the first half first. */ Bezier(pts, 3, 0.5, Left, Right); t = findVertical(Left, tmin, (tmin + tmax) / 2.0, xcoord, ymin, ymax); if (t >= 0.0) return t; return findVertical(Right, (tmin + tmax) / 2.0, tmax, xcoord, ymin, ymax); }
inline Coord *Line::clip(Coord *in, const Coord offset, const Region ®, Coord *out) { double high = 1.0, low = 0.0; bool lowInside = reg.Hit(in[0]-offset), highInside = reg.Hit(in[degree]-offset); if(lowInside == highInside) return in; Coord work[4], *lowSeg,*highSeg; if(lowInside) { lowSeg = 0; highSeg = work; } else { lowSeg = work; highSeg = 0; } do { double t = (high + low) / 2.0; Coord p = Bezier(in,degree,t,lowSeg,highSeg); bool inside = reg.Hit(p-offset); if(inside == lowInside) low = t; else high = t; } while(high - low > DETAIL); /* should be adaptive with resolution */ for(int i=0;i<=degree;++i) out[i] = work[i]; return out; }
static void gd_bezier(point* A, int n, int arrow_at_start, int arrow_at_end) { pointf p0, p1, V[4]; int i, j, step; int style[20]; int pen, width; gdImagePtr brush = NULL; if (cstk[SP].pen != P_NONE) { if (cstk[SP].pen == P_DASHED) { for (i = 0; i < 10; i++) style[i] = cstk[SP].pencolor; for (; i < 20; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 20); pen = gdStyled; } else if (cstk[SP].pen == P_DOTTED) { for (i = 0; i < 2; i++) style[i] = cstk[SP].pencolor; for (; i < 12; i++) style[i] = gdTransparent; gdImageSetStyle(im, style, 12); pen = gdStyled; } else { pen = cstk[SP].pencolor; } #if 0 if (cstk[SP].penwidth != WIDTH_NORMAL) { width=cstk[SP].penwidth; brush = gdImageCreate(width,width); gdImagePaletteCopy(brush, im); gdImageFilledRectangle(brush, 0,0,width-1, width-1, cstk[SP].pencolor); gdImageSetBrush(im, brush); if (pen == gdStyled) pen = gdStyledBrushed; else pen = gdBrushed; } #else width = cstk[SP].penwidth; gdImageSetThickness(im, width); #endif V[3].x = A[0].x; V[3].y = A[0].y; for (i = 0; i+3 < n; i += 3) { V[0] = V[3]; for (j = 1; j <= 3; j++) { V[j].x = A[i+j].x; V[j].y = A[i+j].y; } p0 = gdpt(V[0]); for (step = 1; step <= BEZIERSUBDIVISION; step++) { p1 = gdpt(Bezier(V, 3, (double)step/BEZIERSUBDIVISION, NULL, NULL)); gdImageLine(im, ROUND(p0.x), ROUND(p0.y), ROUND(p1.x), ROUND(p1.y), pen); p0 = p1; } } if (brush) gdImageDestroy(brush); } }
pointf dotneato_closest(splines * spl, pointf pt) { int i, j, k, besti, bestj; double bestdist2, d2, dlow2, dhigh2; /* squares of distances */ double low, high, t; pointf c[4], pt2; bezier bz; besti = bestj = -1; bestdist2 = 1e+38; for (i = 0; i < spl->size; i++) { bz = spl->list[i]; for (j = 0; j < bz.size; j++) { pointf b; b.x = bz.list[j].x; b.y = bz.list[j].y; d2 = DIST2(b, pt); if ((bestj == -1) || (d2 < bestdist2)) { besti = i; bestj = j; bestdist2 = d2; } } } bz = spl->list[besti]; /* Pick best Bezier. If bestj is the last point in the B-spline, decrement. * Then set j to be the first point in the corresponding Bezier by dividing * then multiplying be 3. Thus, 0,1,2 => 0; 3,4,5 => 3, etc. */ if (bestj == bz.size-1) bestj--; j = 3*(bestj / 3); for (k = 0; k < 4; k++) { c[k].x = bz.list[j + k].x; c[k].y = bz.list[j + k].y; } low = 0.0; high = 1.0; dlow2 = DIST2(c[0], pt); dhigh2 = DIST2(c[3], pt); do { t = (low + high) / 2.0; pt2 = Bezier(c, 3, t, NULL, NULL); if (fabs(dlow2 - dhigh2) < 1.0) break; if (fabs(high - low) < .00001) break; if (dlow2 < dhigh2) { high = t; dhigh2 = DIST2(pt2, pt); } else { low = t; dlow2 = DIST2(pt2, pt); } } while (1); return pt2; }
point spline_at_y(splines *spl, int y) { int i,j; double low, high, d, t; pointf c[4], pt2; point pt; static bezier bz; static splines *mem = NULL; if (mem != spl) { mem = spl; for (i = 0; i < spl->size; i++) { bz = spl->list[i]; if (BETWEEN (bz.list[bz.size-1].y, y, bz.list[0].y)) break; } } if (y > bz.list[0].y) pt = bz.list[0]; else if (y < bz.list[bz.size-1].y) pt = bz.list[bz.size - 1]; else { for (i = 0; i < bz.size; i += 3) { for (j = 0; j < 3; j++) { if ((bz.list[i+j].y <= y) && (y <= bz.list[i+j+1].y)) break; if ((bz.list[i+j].y >= y) && (y >= bz.list[i+j+1].y)) break; } if (j < 3) break; } assert (i < bz.size); for (j = 0; j < 4; j++) { c[j].x = bz.list[i + j].x; c[j].y = bz.list[i + j].y; /* make the spline be monotonic in Y, awful but it works for now */ if ((j > 0) && (c[j].y > c[j - 1].y)) c[j].y = c[j - 1].y; } low = 0.0; high = 1.0; do { t = (low + high) / 2.0; pt2 = Bezier (c, 3, t, NULL, NULL); d = pt2.y - y; if (ABS(d) <= 1) break; if (d < 0) high = t; else low = t; } while (1); pt.x = (int)pt2.x; pt.y = (int)pt2.y; } pt.y = y; return pt; }
point dotneato_closest(splines * spl, point p) { int i, j, k, besti, bestj; double bestdist2, d2, dlow2, dhigh2; /* squares of distances */ double low, high, t; pointf c[4], pt2, pt; point rv; bezier bz; besti = bestj = -1; bestdist2 = 1e+38; P2PF(p, pt); for (i = 0; i < spl->size; i++) { bz = spl->list[i]; for (j = 0; j < bz.size; j++) { pointf b; b.x = bz.list[j].x; b.y = bz.list[j].y; d2 = DIST2(b, pt); if ((bestj == -1) || (d2 < bestdist2)) { besti = i; bestj = j; bestdist2 = d2; } } } bz = spl->list[besti]; j = bestj / 3; if (j >= spl->size) j--; for (k = 0; k < 4; k++) { c[k].x = bz.list[j + k].x; c[k].y = bz.list[j + k].y; } low = 0.0; high = 1.0; dlow2 = DIST2(c[0], pt); dhigh2 = DIST2(c[3], pt); do { t = (low + high) / 2.0; pt2 = Bezier(c, 3, t, NULL, NULL); if (fabs(dlow2 - dhigh2) < 1.0) break; if (fabs(high - low) < .00001) break; if (dlow2 < dhigh2) { high = t; dhigh2 = DIST2(pt2, pt); } else { low = t; dlow2 = DIST2(pt2, pt); } } while (1); PF2P(pt2, rv); return rv; }
void VectorFileWriter::BezierAsPwl(SBezier *sb) { List<Vector> lv; ZERO(&lv); sb->MakePwlInto(&lv, SS.ChordTolMm() / SS.exportScale); int i; for(i = 1; i < lv.n; i++) { SBezier sb = SBezier::From(lv.elem[i-1], lv.elem[i]); Bezier(&sb); } lv.Clear(); }
/* splineIntersectf: * Given four spline control points and a box, * find the shortest portion of the spline from * pts[0] to the intersection with the box, if any. * If an intersection is found, the four points are stored in pts[0..3] * with pts[3] being on the box, and 1 is returned. Otherwise, pts * is left unchanged and 0 is returned. */ static int splineIntersectf(pointf * pts, boxf * bb) { double tmin = 2.0; double t; pointf origpts[4]; int i; for (i = 0; i < 4; i++) { origpts[i] = pts[i]; } t = findVertical(pts, 0.0, 1.0, bb->LL.x, bb->LL.y, bb->UR.y); if ((t >= 0) && (t < tmin)) { Bezier(origpts, 3, t, pts, NULL); tmin = t; } t = findVertical(pts, 0.0, MIN(1.0, tmin), bb->UR.x, bb->LL.y, bb->UR.y); if ((t >= 0) && (t < tmin)) { Bezier(origpts, 3, t, pts, NULL); tmin = t; } t = findHorizontal(pts, 0.0, MIN(1.0, tmin), bb->LL.y, bb->LL.x, bb->UR.x); if ((t >= 0) && (t < tmin)) { Bezier(origpts, 3, t, pts, NULL); tmin = t; } t = findHorizontal(pts, 0.0, MIN(1.0, tmin), bb->UR.y, bb->LL.x, bb->UR.x); if ((t >= 0) && (t < tmin)) { Bezier(origpts, 3, t, pts, NULL); tmin = t; } if (tmin < 2.0) { return 1; } else return 0; }
void Bezier(HDC hDC, double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { double A = y4 - y1; double B = x1 - x4; double C = y1 * (x4-x1) - x1 * ( y4-y1); // Ax + By + C = 0 is line (x1,y1) - (x4,y4) double AB = A * A + B * B; // distance from (x2,y2) to the line is less than 1 // distance from (x3,y3) to the line is less than 1 if ( ( A * x2 + B * y2 + C ) * ( A * x2 + B * y2 + C ) < AB ) if ( ( A * x3 + B * y3 + C ) * ( A * x3 + B * y3 + C ) < AB ) { MoveToEx(hDC, (int)x1, (int)y1, NULL); LineTo(hDC, (int)x4, (int)y4); return; } double x12 = x1+x2; double y12 = y1+y2; double x23 = x2+x3; double y23 = y2+y3; double x34 = x3+x4; double y34 = y3+y4; double x1223 = x12+x23; double y1223 = y12+y23; double x2334 = x23+x34; double y2334 = y23+y34; double x = x1223 + x2334; double y = y1223 + y2334; Bezier(hDC, x1, y1, x12/2, y12/2, x1223/4, y1223/4, x/8, y/8); Bezier(hDC, x/8, y/8, x2334/4, y2334/4, x34/2, y34/2, x4, y4); }
int main() { int gdriver=DETECT,gmode; initgraph(&gdriver,&gmode," "); cleardevice(); int i; memset(B,0,sizeof(B));//初始化数组全为0 memset(P,0,sizeof(P)); for(i=0;i<sizeof(t)/sizeof(double);i++) { B[i][0]=(1-t[i])*(1-t[i])*(1-t[i]); B[i][1]=3*t[i]*(1-t[i])*(1-t[i]); B[i][2]=3*t[i]*t[i]*(1-t[i]); B[i][3]=t[i]*t[i]*t[i]; } /*for(i=0;i<7;i++) { for(j=0;j<4;j++) { printf("%f ",B[i][j]); } printf("\n"); }*/ //输出B矩阵 Bezier(50,100, 80,230, 100,270 ,140,160); Bezier(140,160, 180,50, 240,65, 270,120); Bezier(270,120, 330,230, 380,230, 430,150); /*for(i=0;i<7;i++) { for(j=0;j<2;j++) { printf("%f ",P[i][j]); } printf("\n"); }*/ //输出P矩阵 getch(); closegraph(); return 0; }
void Draw_Bezier(float width, float height) { float x = width / 2; float y = height / 2; Matrix4 t; t.makeTranslate(-x, -y, 0); Matrix4 c = objCamera.c; c = t*c; c.transpose(); glLoadMatrixd(c.getPointer()); glColor3f(0, 0, 1); my = Bezier(width, height, angle); for (float t1 = -0.5; t1 < 0.49; t1 += 0.01) { for (float t2 = -0.5; t2 < 0.49; t2 += 0.01) { my.tessellate(t1, t2, .1); } } t.makeTranslate(x, -y, 0); c = objCamera.c; c = t*c; c.transpose(); glLoadMatrixd(c.getPointer()); glColor3f(1, 0, 0); my2 = Bezier(width, height, angle); for (float t1 = -0.5; t1 < 0.49; t1 += 0.01) { for (float t2 = -0.5; t2 < 0.49; t2 += 0.01) { my.tessellate(t1, t2, .1); } } }
QImage Polygon::getImage(int width, int height) { this->width = width; this->height = height; lines.clear(); QImage backBuffer(width, height, QImage::Format_RGB888); backBuffer.fill(qRgb(255, 255, 255)); //drawBezier(&backBuffer, Qt::black); Bezier(&backBuffer, points[0].x(),points[0].y(), points[1].x(), points[1].y(), points[2].x(), points[2].y(), points[3].x(), points[3].y(), Qt::black); return backBuffer; }
point dotneato_closest(splines* spl, point p) { int i, j, k, besti, bestj; double bestdist, d, dlow, dhigh; double low, high, t; pointf c[4], pt2, pt; point rv; bezier bz; besti = bestj = -1; bestdist = 1e+38; pt.x = p.x; pt.y = p.y; for (i = 0; i < spl->size; i++) { bz = spl->list[i]; for (j = 0; j < bz.size; j++) { pointf b; b.x = bz.list[j].x; b.y = bz.list[j].y; d = dist(b,pt); if ((bestj == -1) || (d < bestdist)) { besti = i; bestj = j; bestdist = d; } } } bz = spl->list[besti]; j = bestj/3; if (j >= spl->size) j--; for (k = 0; k < 4; k++) { c[k].x = bz.list[j + k].x; c[k].y = bz.list[j + k].y; } low = 0.0; high = 1.0; dlow = dist(c[0],pt); dhigh = dist(c[3],pt); do { t = (low + high) / 2.0; pt2 = Bezier (c, 3, t, NULL, NULL); if (fabs(dlow - dhigh) < 1.0) break; if (low == high) break; if (dlow < dhigh) {high = t; dhigh = dist(pt2,pt);} else {low = t; dlow = dist(pt2,pt); } } while (1); rv.x = (int)pt2.x; rv.y = (int)pt2.y; return rv; }
static void vrml_bezier(GVJ_t *job, pointf * A, int n, int arrow_at_start, int arrow_at_end, int filled) { obj_state_t *obj = job->obj; edge_t *e = obj->u.e; double fstz, sndz; pointf p1, V[4]; int i, j, step; assert(e); fstz = Fstz = obj->tail_z; sndz = Sndz = obj->head_z; if (straight(A,n)) { doSegment (job, A, gvrender_ptf(job, ND_coord(agtail(e))),Fstz,gvrender_ptf(job, ND_coord(aghead(e))),Sndz); return; } gvputs(job, "Shape { geometry Extrusion {\n"); gvputs(job, " spine ["); V[3] = A[0]; for (i = 0; i + 3 < n; i += 3) { V[0] = V[3]; for (j = 1; j <= 3; j++) V[j] = A[i + j]; for (step = 0; step <= BEZIERSUBDIVISION; step++) { p1 = Bezier(V, 3, (double) step / BEZIERSUBDIVISION, NULL, NULL); gvprintf(job, " %.3f %.3f %.3f", p1.x, p1.y, interpolate_zcoord(job, p1, A[0], fstz, A[n - 1], sndz)); } } gvputs(job, " ]\n"); gvprintf(job, " crossSection [ %.3f %.3f, %.3f %.3f, %.3f %.3f, %.3f %.3f ]\n", (obj->penwidth), (obj->penwidth), -(obj->penwidth), (obj->penwidth), -(obj->penwidth), -(obj->penwidth), (obj->penwidth), -(obj->penwidth)); gvputs(job, "}\n"); gvprintf(job, " appearance DEF E%ld Appearance {\n", AGSEQ(e)); gvputs(job, " material Material {\n"); gvputs(job, " ambientIntensity 0.33\n"); gvprintf(job, " diffuseColor %.3f %.3f %.3f\n", obj->pencolor.u.rgba[0] / 255., obj->pencolor.u.rgba[1] / 255., obj->pencolor.u.rgba[2] / 255.); gvputs(job, " }\n"); gvputs(job, " }\n"); gvputs(job, "}\n"); }
/* * FindRoots : * Given a 5th-degree equation in Bernstein-Bezier form, find * all of the roots in the interval [0, 1]. Return the number * of roots found. */ int Measurement::FindRoots(QPointF* w, int degree,double *t,int depth) { int i; QPointF Left[W_DEGREE+1], /* New left and right */ Right[W_DEGREE+1]; /* control polygons */ int left_count, /* Solution count from */ right_count; /* children */ double left_t[W_DEGREE+1], /* Solutions from kids */ right_t[W_DEGREE+1]; switch (CrossingCount(w, degree)) { case 0 : { /* No solutions here */ return 0; } case 1 : { /* Unique solution */ /* Stop recursion when the tree is deep enough */ /* if deep enough, return 1 solution at midpoint */ if (depth >= MAXDEPTH) { t[0] = (w[0].rx() + w[W_DEGREE].rx()) / 2.0; return 1; } if (ControlPolygonFlatEnough(w, degree)) { t[0] = ComputeXIntercept(w, degree); return 1; } break; } } /* Otherwise, solve recursively after */ /* subdividing control polygon */ Bezier(w, degree, 0.5, Left, Right); left_count = FindRoots(Left, degree, left_t, depth+1); right_count = FindRoots(Right, degree, right_t, depth+1); /* Gather solutions together */ for (i = 0; i < left_count; i++) { t[i] = left_t[i]; } for (i = 0; i < right_count; i++) { t[i+left_count] = right_t[i]; } /* Send back total number of solutions */ return (left_count+right_count); }
/* * find_bezier_roots : Given an equation in Bernstein-Bezier form, find all * of the roots in the interval [0, 1]. Return the number of roots found. */ void find_parametric_bezier_roots(Geom::Point const *w, /* The control points */ unsigned degree, /* The degree of the polynomial */ std::vector<double> &solutions, /* RETURN candidate t-values */ unsigned depth) /* The depth of the recursion */ { total_steps++; const unsigned max_crossings = crossing_count(w, degree); switch (max_crossings) { case 0: /* No solutions here */ return; case 1: /* Unique solution */ /* Stop recursion when the tree is deep enough */ /* if deep enough, return 1 solution at midpoint */ if (depth >= MAXDEPTH) { solutions.push_back((w[0][Geom::X] + w[degree][Geom::X]) / 2.0); return; } // I thought secant method would be faster here, but it'aint. -- njh if (control_poly_flat_enough(w, degree)) { solutions.push_back(compute_x_intercept(w, degree)); return; } break; } /* * Otherwise, solve recursively after subdividing control polygon * New left and right control polygons */ Geom::Point *Left = new Geom::Point[degree+1]; Geom::Point *Right = new Geom::Point[degree+1]; Bezier(w, degree, 0.5, Left, Right); total_subs ++; find_parametric_bezier_roots(Left, degree, solutions, depth+1); find_parametric_bezier_roots(Right, degree, solutions, depth+1); delete[] Left; delete[] Right; }
void Shape::addBezier(vector<Point> *result) { vector<Point> temp; temp = points; for(int i=0; i<temp.size(); i++) { if(temp[i].tag==0) { vector<Point> control; vector<Point> bezier; control.push_back(temp[i]); i++; while(i<temp.size() && temp[i].tag==1) { control.push_back(temp[i]); i++; } if(i>=temp.size()) { control.push_back(temp[0]); } else { control.push_back(temp[i]); if(i>=temp.size()) control.push_back(temp[0]); } //jika isi control>2, berarti bezier if(control.size()>2) { Bezier(control, &bezier); for(int j=0; j<bezier.size(); j++){ result->push_back(bezier[j]); } } else { for(int j=0; j<control.size(); j++){ result->push_back(control[j]); } } i--; } } }
void Style::active_bezier() { if (npara == 3) { graybg(); int centerx, centery, a = parameters[2]; if (item) { centerx = item->layer->startx + parameters[0]; centery = item->layer->starty + parameters[1]; } setcolor(BLACK); if (item) { rectangle(item->layer->startx, item->layer->starty, item->layer->endx, item->layer->endy); } vector<Point> control; control.push_back(Point(centerx, item->layer->starty)); control.push_back(Point(item->layer->startx, centery - a / 2)); control.push_back(Point(item->layer->endx, centery + a / 2)); control.push_back(Point(centerx, item->layer->endy)); Bezier(control, BLACK); } }
Position Line::Intersection(int seg,Segment other) { switch(degree) { case 1: return lines_intersect(Segment(at(seg),at(seg+1)),other); case 3: double roots[4]; /* if(between(other.a,at(seg),other.b)) return Position(at(seg)); if(between(other.a,at(seg+3),other.b)) return Position(at(seg+3)); */ if(splineIntersectsLine(&at(seg),other,roots)>0) return Position(Bezier(&at(seg),3,roots[0])); else return Position(); default: case 0: return Position(); } }
void VectorFileWriter::BezierAsNonrationalCubic(SBezier *sb, int depth) { Vector t0 = sb->TangentAt(0), t1 = sb->TangentAt(1); // The curve is correct, and the first derivatives are correct, at the // endpoints. SBezier bnr = SBezier::From( sb->Start(), sb->Start().Plus(t0.ScaledBy(1.0/3)), sb->Finish().Minus(t1.ScaledBy(1.0/3)), sb->Finish()); double tol = SS.ChordTolMm() / SS.exportScale; // Arbitrary choice, but make it a little finer than pwl tolerance since // it should be easier to achieve that with the smooth curves. tol /= 2; bool closeEnough = true; int i; for(i = 1; i <= 3; i++) { double t = i/4.0; Vector p0 = sb->PointAt(t), pn = bnr.PointAt(t); double d = (p0.Minus(pn)).Magnitude(); if(d > tol) { closeEnough = false; } } if(closeEnough || depth > 3) { Bezier(&bnr); } else { SBezier bef, aft; sb->SplitAt(0.5, &bef, &aft); BezierAsNonrationalCubic(&bef, depth+1); BezierAsNonrationalCubic(&aft, depth+1); } }
Position Line::YIntersection(double y) { if(!size()) return Position(); for(unsigned i = 0; i < size(); i += degree) if(at(i).y == y) return Position(at(i)); int seg = GetSeg(y); if(seg < 0) return Position(); double high,low; if(at(seg).y < at(seg+degree).y) { high = 1.0; low = 0.0; } else { high = 0.0; low = 1.0; } double close = DBL_MAX; Coord ret; do { double t = (high + low) / 2.0; Coord p = Bezier(&at(seg),degree,t); double d = absol(p.y - y); if(d < close) { ret = p; close = d; } if(p.y > y) high = t; else low = t; } while(absol(high - low) > .01); /* should be adaptive */ return Position(ret); }
void Style::normal_bezier() { if (npara == 3) { setlinestyle(SOLID_LINE, 0, NORM_WIDTH); setfillstyle(SOLID_FILL, WHITE); if (item) { bar(item->layer->startx + 1, item->layer->starty + 1, item->layer->endx, item->layer->endy); } int centerx, centery, a = parameters[2]; if (item) { centerx = item->layer->startx + parameters[0]; centery = item->layer->starty + parameters[1]; } setcolor(BLACK); if (item) { rectangle(item->layer->startx, item->layer->starty, item->layer->endx, item->layer->endy); } vector<Point> control; control.push_back(Point(centerx, item->layer->starty)); control.push_back(Point(item->layer->startx, centery - a / 2)); control.push_back(Point(item->layer->endx, centery + a / 2)); control.push_back(Point(centerx, item->layer->endy)); Bezier(control, BLACK); } }
//Display void display (void) { glClearColor(rosso_sf,verde_sf,blu_sf,0.0);//rendo variabili i parametri che mi definiscono il colore glClear(GL_COLOR_BUFFER_BIT); int i; glColor3f(0.0,0.0,1.0); glPointSize(dimpunto); glBegin(GL_POINTS);//per visualizzare anche i punti dove si clicca di colore blu for (i=1;i<=last;i++) glVertex2f(Punti[i].x,Punti[i].y); glEnd(); glColor3f(rosso_dis,verde_dis,blu_dis); glBegin(GL_LINE_STRIP); //poligono di controllo for (i=1;i<=last;i++) glVertex2f(Punti[i].x,Punti[i].y); glEnd(); n=last;//setto n al numero di punti disegnato for(i=1;i<=n;i++) w[i]=1;//metto tutti i pesi a 1 //scelta parametrizzazione if (scelta_param==0) { Parametrizzazione_Uniforme(); } else if(scelta_param==1) { Parametrizzazione_Corde(); } //scelta della funzione glPointSize(2);//la curva la disegno sempre di dimensione 2 if (metodo=='H' && last>1) { Hermite(); Disegna_Funzioni_Base(); } if (metodo=='B' && last>1) { if(mod_pesi_bez==1) w[i_p_b]=val_peso; Bezier(); if (subd==1) Subdivision(); if (d_el==1) Degree_Elevation(); Disegna_fBaseBernstein(); } if (metodo=='S' && last>3) { if(mod_pesi_spline==1) w[i_p_s]=val_pesos; Costruisci_Nodi(); Funzioni_Bspline(Nodi); De_Boor(); } //glutPostRedisplay();//è per questo che le funzioni base saltellano :)...se non lo metti però quando cambi il metodo non viene cambiato immediatamente ma dopo aver spinto un altro punto glFlush(); }