Beispiel #1
0
double Bernsteins::secant(Bezier bz) {
    double s = 0, t = 1;
    double e = 1e-14;
    int side = 0;
    double r, fr, fs = bz.at0(), ft = bz.at1();

    for (size_t n = 0; n < 100; ++n)
    {
        r = (fs*t - ft*s) / (fs - ft);
        if (fabs(t-s) < e * fabs(t+s)) {
            debug(std::cout << "error small " << fabs(t-s) 
                      << ", accepting solution " << r 
                  << "after " << n << "iterations\n");
            return r;
        }

        fr = horner(bz, r);

        if (fr * ft > 0)
        {
            t = r; ft = fr;
            if (side == -1) fs /= 2;
            side = -1;
        }
        else if (fs * fr > 0)
        {
            s = r;  fs = fr;
            if (side == +1) ft /= 2;
            side = +1;
        }
        else break;
    }
    return r;
}
Beispiel #2
0
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);
		}
	}
}
Beispiel #3
0
	void ShapeMaker::cubicTo (const Bezier &cubic)
	{
		const double sqrt3 = 1.7320508075688772935274463415059;
		const double precision = 600 * 18 / (60 * factorx * sqrt3);

		// distance between control points of quadratic approximations of either end
		double D01 = (cubic.p1 - (cubic.c1 - cubic.c0) * 3 - cubic.p0).magnitude () / 2;

		double tMax3 = precision / D01;
		if (tMax3 >= 1)
		{
			curveTo (cubic.quadraticCtrl(), cubic.p1);
			return;
		}

		Bezier end(cubic);

		if (tMax3 >= 0.5 * 0.5 * 0.5)
		{
			Bezier start (end.split (0.5));
			curveTo (start.quadraticCtrl (), start.p1);
		}
		else
		{
			double tMax = pow (tMax3, 1.0/3.0);
			Bezier start (end.split (tMax));
			Bezier middle (end.split (1 - tMax / (1 - tMax)));

			curveTo (start.quadraticCtrl (), start.p1);
			cubicTo (middle);
		}

		curveTo (end.quadraticCtrl (), end.p1);
	}
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));
	}
}
Beispiel #5
0
CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf,
                            const Bezier &rCurve, VarPercent &rVariable,
                            int thickness, GenericBitmap *pBackground,
                            int nbHoriz, int nbVert, int padHoriz, int padVert,
                            VarBool *pVisible, const UString &rHelp ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_pCursor( NULL ),
    m_rVariable( rVariable ), m_thickness( thickness ), m_rCurve( rCurve ),
    m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
    m_pImgSeq( pBackground ), m_nbHoriz( nbHoriz ), m_nbVert( nbVert ),
    m_padHoriz( padHoriz ), m_padVert( padVert ), m_bgWidth( 0 ),
    m_bgHeight( 0 ), m_position( 0 )
{
    if( pBackground )
    {
        // Build the background image sequence
        // Note: we suppose that the last padding is not included in the
        // given image
        // TODO: we should probably change this assumption, as it would make
        // the code a bit simpler and it would be more natural for the skins
        // designers
        m_bgWidth = (pBackground->getWidth() + m_padHoriz) / nbHoriz;
        m_bgHeight = (pBackground->getHeight() + m_padVert) / nbVert;

        // Observe the position variable
        m_rVariable.addObserver( this );

        // Initial position
        m_position = (int)( m_rVariable.get() * (m_nbHoriz * m_nbVert - 1) );
    }
}
Beispiel #6
0
void Bezier::attach(Bezier& other, bool reverse) {
	nextPatch = &other;

	// Calculate road radius as the connection of this and the next patch
	MathVector<float, 3> a = surfCoord(0.5, 0.0), b = surfCoord(0.5, 1.0), c = other.surfCoord(0.5, 1.0);
	if (reverse) { a = surfCoord(0.5, 1.0); b = surfCoord(0.5, 0.0); c = other.surfCoord(0.5, 0.0); }

	MathVector<float, 3> d1 = a - b, d2 = c - b;
	float diff = d2.magnitude() - d1.magnitude();
	float dd = ((d1.magnitude() < 0.0001) || (d2.magnitude() < 0.0001)) ?
			     0.f : d1.normalized().dot(d2.normalized());
	float angle = acosf((dd >= 1.f) ? 1.f :(dd <= -1.f) ? -1.f : dd);
	float d1d2mag = d1.magnitude() + d2.magnitude();
	float alpha = (d1d2mag < 0.0001) ? 0.f : (float) (M_PI * diff + 2.f * d1.magnitude() * angle) / d1d2mag / 2.f;

	if (fabs(alpha - M_PI/2.0) < 0.001) roadRadius = 10000.0;
	else roadRadius = d1.magnitude() / 2.f / cosf(alpha);

	if (d1.magnitude() < 0.0001) roadCurvature = 0.0;
	else roadCurvature = 2.f * cosf(alpha) / d1.magnitude();

	// Determine it's a left or right turn at the connection
	MathVector<float, 3> d = d1.cross(d2);
	if (fabs(d[0]) < 0.1 && fabs(d[1]) < 0.1 && fabs(d[2]) < 0.1) turn = 0; // Straight road ahead
	else if (d[1] > 0.0) turn = -1; // Left turn ahead
	else turn = 1; // Right turn ahead

	// Calculate distance from start of the road
	length = d1.magnitude();
}
Beispiel #7
0
float AiCarStandard::GetHorizontalDistanceAlongPatch(const Bezier & patch, Vec3 carposition)
{
	Vec3 leftside = (patch.GetPoint(0,0) + patch.GetPoint(3,0))*0.5;
	Vec3 rightside = (patch.GetPoint(0,3) + patch.GetPoint(3,3))*0.5;
	Vec3 patchwidthvector = rightside - leftside;
	return patchwidthvector.Normalize().dot(carposition-leftside);
}
Beispiel #8
0
void drawPath()
{
	for (float g = 0; g < 1; g += .005)
	{
		glColor3f(0, 0, 1);
		Vector4 test = x1.lip(g, .1);
		drawDots(test);
	}
	for (float g = 0; g < 1; g += .005)
	{
		glColor3f(1, 1, 0);
		Vector4 test = x2.lip(g, .1);
		drawDots(test);
	}
	for (float g = 0; g < 1; g += .005)
	{
		glColor3f(1, 0, 0);
		Vector4 test = x3.lip(g, .1);
		drawDots(test);
	}
	for (float g = 0; g < 1; g += .005)
	{
		glColor3f(1, 1, 1);
		Vector4 test = x4.lip(g, .1);
		drawDots(test);
	}
}
Beispiel #9
0
void convex_hull_marching(Bezier src_bz, Bezier bz,
                          std::vector<double> &solutions,
                          double left_t,
                          double right_t)
{
    while(bz.order() > 0 and bz[0] == 0) {
        std::cout << "deflate\n";
        bz = bz.deflate();
        solutions.push_back(left_t);
    }
    if (bz.order() > 0) {
    
        int old_sign = SGN(bz[0]);
    
        int sign;
        double left_bound = 0;
        double dt = 0;
        for (size_t i = 1; i < bz.size(); i++)
        {
            sign = SGN(bz[i]);
            if (sign != old_sign)
            {
                dt = double(i) / bz.order();
                left_bound = dt * bz[0] / (bz[0] - bz[i]);
                break;
            }
            old_sign = sign;
        }
        if (dt == 0) return;
        std::cout << bz << std::endl;
        std::cout << "dt = " << dt << std::endl;
        std::cout << "left_t = " << left_t << std::endl;
        std::cout << "right_t = " << right_t << std::endl;
        std::cout << "left bound = " << left_bound 
                  << " = " << bz(left_bound) << std::endl; 
        double new_left_t = left_bound * (right_t - left_t) + left_t;
        std::cout << "new_left_t = " << new_left_t << std::endl;
        Bezier bzr = subRight(src_bz, new_left_t);
        while(bzr.order() > 0 and bzr[0] == 0) {
            std::cout << "deflate\n";
            bzr = bzr.deflate();
            solutions.push_back(new_left_t);
        }
        if (left_t < new_left_t) {
            convex_hull_marching(src_bz, bzr,
                                 solutions,
                                 new_left_t, right_t); 
        } else {
            std::cout << "epsilon reached\n";
            while(bzr.order() > 0 and fabs(bzr[0]) <= 1e-10) {
                std::cout << "deflate\n";
                bzr = bzr.deflate();
                std::cout << bzr << std::endl;
                solutions.push_back(new_left_t);
            }

        }
    }
}
Beispiel #10
0
bool Bezier::operator!=(const Bezier & other) const
{
	if (m_isEmpty != other.isEmpty()) return true;
	if (m_cp0 != other.cp0()) return true;
	if (m_cp1 != other.cp1()) return true;

	return false;
}
Beispiel #11
0
CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf, CtrlSliderCursor &rCursor,
                            const Bezier &rCurve, VarPercent &rVariable,
                            int thickness, VarBool *pVisible,
                            const UString &rHelp ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_rCursor( rCursor ),
    m_rVariable( rVariable ), m_thickness( thickness ), m_rCurve( rCurve ),
    m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() )
{
}
Beispiel #12
0
CtrlSliderCursor::CtrlSliderCursor( intf_thread_t *pIntf,
                                    const GenericBitmap &rBmpUp,
                                    const GenericBitmap &rBmpOver,
                                    const GenericBitmap &rBmpDown,
                                    const Bezier &rCurve,
                                    VarPercent &rVariable,
                                    VarBool *pVisible,
                                    const UString &rTooltip,
                                    const UString &rHelp ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
    m_rVariable( rVariable ), m_tooltip( rTooltip ),
    m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
    m_cmdOverDown( this, &transOverDown ),
    m_cmdDownOver( this, &transDownOver ), m_cmdOverUp( this, &transOverUp ),
    m_cmdUpOver( this, &transUpOver ), m_cmdMove( this, &transMove ),
    m_cmdScroll( this, &transScroll ),
    m_lastPercentage( 0 ), m_xOffset( 0 ), m_yOffset( 0 ),
    m_pEvt( NULL ), m_rCurve( rCurve )
{
    // Build the images of the cursor
    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
    m_pImgUp = pOsFactory->createOSGraphics( rBmpUp.getWidth(),
               rBmpUp.getHeight() );
    m_pImgUp->drawBitmap( rBmpUp, 0, 0 );
    m_pImgDown = pOsFactory->createOSGraphics( rBmpDown.getWidth(),
                 rBmpDown.getHeight() );
    m_pImgDown->drawBitmap( rBmpDown, 0, 0 );
    m_pImgOver = pOsFactory->createOSGraphics( rBmpOver.getWidth(),
                 rBmpOver.getHeight() );
    m_pImgOver->drawBitmap( rBmpOver, 0, 0 );

    // States
    m_fsm.addState( "up" );
    m_fsm.addState( "over" );
    m_fsm.addState( "down" );

    // Transitions
    m_fsm.addTransition( "over", "mouse:left:down", "down",
                         &m_cmdOverDown );
    m_fsm.addTransition( "down", "mouse:left:up", "over",
                         &m_cmdDownOver );
    m_fsm.addTransition( "over", "leave", "up", &m_cmdOverUp );
    m_fsm.addTransition( "up", "enter", "over", &m_cmdUpOver );
    m_fsm.addTransition( "down", "motion", "down", &m_cmdMove );
    m_fsm.addTransition( "over", "scroll", "over", &m_cmdScroll );

    // Initial state
    m_fsm.setState( "up" );
    m_pImg = m_pImgUp;

    // Observe the position variable
    m_rVariable.addObserver( this );

    // Initial position of the cursor
    m_lastPercentage = m_rVariable.get();
}
Beispiel #13
0
bool are_equal(Bezier A, Bezier B) {
    int maxSize = max(A.size(), B.size());
    double t = 0., dt = 1./maxSize;
    
    for(int i = 0; i <= maxSize; i++) {
        EXPECT_FLOAT_EQ(A.valueAt(t), B.valueAt(t));// return false;
        t += dt;
    }
    return true;
}
/** Changes the basis of p to be bernstein.
 \param p the Symmetric basis polynomial
 \returns the Bernstein basis polynomial

 if the degree is even q is the order in the symmetrical power basis,
 if the degree is odd q is the order + 1
 n is always the polynomial degree, i. e. the Bezier order
 sz is the number of bezier handles.
*/
void sbasis_to_bezier (Bezier & bz, SBasis const& sb, size_t sz)
{
    if (sb.size() == 0) {
        THROW_RANGEERROR("size of sb is too small");
    }

    size_t q, n;
    bool even;
    if (sz == 0)
    {
        q = sb.size();
        if (sb[q-1][0] == sb[q-1][1])
        {
            even = true;
            --q;
            n = 2*q;
        }
        else
        {
            even = false;
            n = 2*q-1;
        }
    }
    else
    {
        q = (sz > 2*sb.size()-1) ?  sb.size() : (sz+1)/2;
        n = sz-1;
        even = false;
    }
    bz.clear();
    bz.resize(n+1);
    double Tjk;
    for (size_t k = 0; k < q; ++k)
    {
        for (size_t j = k; j < n-k; ++j) // j <= n-k-1
        {
            Tjk = binomial(n-2*k-1, j-k);
            bz[j] += (Tjk * sb[k][0]);
            bz[n-j] += (Tjk * sb[k][1]); // n-k <-> [k][1]
        }
    }
    if (even)
    {
        bz[q] += sb[q][0];
    }
    // the resulting coefficients are with respect to the scaled Bernstein
    // basis so we need to divide them by (n, j) binomial coefficient
    for (size_t j = 1; j < n; ++j)
    {
        bz[j] /= binomial(n, j);
    }
    bz[0] = sb[0][0];
    bz[n] = sb[0][1];
}
Beispiel #15
0
// suggested by Sederberg.
double Bernsteins::horner(Bezier bz, double t)
{
    double u, tn, tmp;
    u = 1.0 - t;
    tn = 1.0;
    tmp = bz.at0() * u;
    for(size_t i = 1; i < bz.degree(); ++i)
    {
        tn *= t;
        tmp = (tmp + tn*choose<double>(bz.order(), (unsigned)i)*bz[i]) * u;
    }
    return (tmp + tn*t*bz.at1());
}
/** Find all t s.t s(t) = 0
 \param a sbasis function
 \returns vector of zeros (roots)

*/
std::vector<double> roots(SBasis const & s) {
    switch(s.size()) {
        case 0:
            return std::vector<double>();
        case 1:
            return roots1(s);
        default:
        {
            Bezier bz;
            sbasis_to_bezier(bz, s);
            return bz.roots();
        }
    }
}
Beispiel #17
0
Bezier Bezier::join(const Bezier * other) const
{
	Bezier bezier;
	bool otherIsEmpty = (other == NULL || other->isEmpty());

	if (isEmpty() && otherIsEmpty) {
		return bezier;
	}
	else {
		if (isEmpty()) {
			bezier.set_cp0(m_endpoint0);
			bezier.set_cp1(other->cp1());
		}
		else if (other->isEmpty()) {
			bezier.set_cp1(other->m_endpoint1);
			bezier.set_cp0(cp0());
		}
		else {
			bezier.set_cp0(cp0());
			bezier.set_cp1(other->cp1());
		}
	}

	return bezier;
}
Beispiel #18
0
Bezier Bezier::fromElement(QDomElement & element) 
{
	Bezier bezier;
	if (element.tagName().compare("bezier") != 0) return bezier;

	QDomElement point = element.firstChildElement("cp0");
	if (point.isNull()) return bezier;

	double x = point.attribute("x").toDouble();
	double y = point.attribute("y").toDouble();
	bezier.set_cp0(QPointF(x, y));

	point = element.firstChildElement("cp1");
	x = point.attribute("x").toDouble();
	y = point.attribute("y").toDouble();
	bezier.set_cp1(QPointF(x, y));

	return bezier;
}
Beispiel #19
0
ActionRetCodeEnum
RotoShapeRenderNode::isIdentity(TimeValue time,
                                const RenderScale & scale,
                                const RectI & roi,
                                ViewIdx view,
                                const ImagePlaneDesc& /*plane*/,
                                TimeValue* inputTime,
                                ViewIdx* inputView,
                                int* inputNb,
                                ImagePlaneDesc* /*inputPlane*/)
{
    *inputView = view;
    NodePtr node = getNode();

    *inputNb = -1;
    RotoDrawableItemPtr rotoItem = getAttachedRotoItem();
    if (!rotoItem) {
        return eActionStatusFailed;
    }
    Bezier* isBezier = dynamic_cast<Bezier*>(rotoItem.get());
    if (!rotoItem || !rotoItem->isActivated(time, view) || (isBezier && ((!isBezier->isCurveFinished(view) && !isBezier->isOpenBezier()) || isBezier->getControlPointsCount(view) <= 1))) {
        *inputTime = time;
        *inputNb = 0;

        return eActionStatusOK;
    }

    bool isPainting = isDuringPaintStrokeCreation();
    RectD maskRod;
    getRoDFromItem(rotoItem, time, view, isPainting, &maskRod);

    RectI maskPixelRod;
    maskRod.toPixelEnclosing(scale, getAspectRatio(-1), &maskPixelRod);
    if ( !maskPixelRod.intersects(roi) ) {
        *inputTime = time;
        *inputNb = 0;
    }
    
    return eActionStatusOK;
} // isIdentity
Beispiel #20
0
double AiCarStandard::GetPatchRadius(const Bezier & patch)
{
	if (patch.GetNextPatch() && patch.GetNextPatch()->GetNextPatch())
	{
		double track_radius = 0;

		/*Vec3 d1 = -GetPatchDirection(patch);
		Vec3 d2 = GetPatchDirection(*patch.GetNextPatch());*/
		Vec3 d1 = -(patch.GetNextPatch()->GetRacingLine() - patch.GetRacingLine());
		Vec3 d2 = patch.GetNextPatch()->GetNextPatch()->GetRacingLine() - patch.GetNextPatch()->GetRacingLine();
		d1[2] = 0;
		d2[2] = 0;
		float d1mag = d1.Magnitude();
		float d2mag = d2.Magnitude();
		float diff = d2mag - d1mag;
		double dd = ((d1mag < 0.0001) || (d2mag < 0.0001)) ? 0.0 : d1.Normalize().dot(d2.Normalize());
		float angle = acos((dd>=1.0L)?1.0L:(dd<=-1.0L)?-1.0L:dd);
		float d1d2mag = d1mag + d2mag;
		float alpha = (d1d2mag < 0.0001) ? 0.0f : (M_PI * diff + 2.0 * d1mag * angle) / d1d2mag / 2.0;
		if (fabs(alpha - M_PI/2.0) < 0.001) track_radius = 10000.0;
		else track_radius = d1mag / 2.0 / cos(alpha);

		return track_radius;
	}
	else //fall back
		return 0;
}
Beispiel #21
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);
		}
	}
}
Beispiel #22
0
TEST(Bezier, BezierFunctions) {
	MathVector<float, 3> p[4], l[4], r[4];
	p[0].set(-1,0,0); p[1].set(-1,1,0); p[2].set(1,1,0); p[3].set(1,0,0);

	Bezier b; b.deCasteljauHalveCurve(p, l, r);

	EXPECT_EQ(l[0],(MathVector<float, 3>(-1, 0, 0)));
	EXPECT_EQ(l[1],(MathVector<float, 3>(-1, 0.5, 0)));
	EXPECT_EQ(l[2],(MathVector<float, 3>(-0.5, 0.75, 0)));
	EXPECT_EQ(l[3],(MathVector<float, 3>(0, 0.75, 0)));

	EXPECT_EQ(r[3],(MathVector<float, 3>(1, 0, 0)));
	EXPECT_EQ(r[2],(MathVector<float, 3>(1, 0.5, 0)));
	EXPECT_EQ(r[1],(MathVector<float, 3>(0.5, 0.75, 0)));
	EXPECT_EQ(r[0],(MathVector<float, 3>(0, 0.75, 0)));

	//TODO Commented due to "stack smashing" error
//	b.setFromCorners(MathVector<float, 3>(1, 0, 1),
//					 MathVector<float, 3>(-1, 0, 1),
//					 MathVector<float, 3>(1, 0, -1),
//					 MathVector<float, 3>(-1,0,-1));
//	EXPECT_FALSE(b.checkForProblems());
}
Beispiel #23
0
void draw()
{
	glColor3f(0, 1, 0);

	if (i < 1)
	{
		glColor3f(0, 1, 0);
		Vector4 test = x1.lip(i, .1);
		drawSphere(test);
		i += .005;
	}
	else if (i >= 1 && i2 < 1)
	{
		Vector4 test = x2.lip(i2, .1);
		drawSphere(test);
		i2 += .005;
	}
	else if (i2 >= 1 && i3 < 1)
	{
		Vector4 test = x3.lip(i3, .1);
		drawSphere(test);
		i3 += .005;
	}
	else
	{
		Vector4 test = x4.lip(i4, .1);
		drawSphere(test);
		i4 += .005;
		if (i4 > .99)
		{
			i = 0;
			i2 = 0;
			i3 = 0;
			i4 = 0;
		}
	}
}
Beispiel #24
0
void
Bezier::find_bezier_roots(std::vector<double> &solutions,
                          double left_t, double right_t) const {
    Bezier bz = *this;
    //convex_hull_marching(bz, bz, solutions, left_t, right_t);
    //return;

    // a constant bezier, even if identically zero, has no roots
    if (bz.isConstant()) {
        return;
    }

    while(bz[0] == 0) {
        debug(std::cout << "deflate\n");
        bz = bz.deflate();
        solutions.push_back(0);
    }
    if (bz.degree() == 1) {
        debug(std::cout << "linear\n");

        if (SGN(bz[0]) != SGN(bz[1])) {
            double d = bz[0] - bz[1];
            if(d != 0) {
                double r = bz[0] / d;
                if(0 <= r && r <= 1)
                    solutions.push_back(r);
            }
        }
        return;
    }

    //std::cout << "initial = " << bz << std::endl;
    Bernsteins B(solutions);
    B.find_bernstein_roots(bz, 0, left_t, right_t);
    //std::cout << solutions << std::endl;
}
Beispiel #25
0
	void ShapeMaker::cubicTo(double x1, double y1, double x2, double y2, double ax, double ay) {
		Point a(lastx,lasty);
		Point b(x1,y1);
		Point c(x2,y2);
		Point d(ax,ay);

		Bezier cubic (a, b, c, d);

		double t0, t1;
		int cInflections = cubic.computeInflections (t0, t1);

		if (cInflections == 0)
		{
			cubicTo(cubic);
		}
		else if (cInflections == 1)
		{
			Bezier cubic0 = cubic.split (t0);
			cubicTo (cubic0);
			cubicTo (cubic);
		}
		else
		{
			Bezier cubic0 = cubic.split (t0);
			cubicTo (cubic0);

			Bezier cubic1 = cubic.split (1 - (1 - t1) / (1 - t0));
			cubicTo (cubic1);

			cubicTo (cubic);
		}

		lastx = ax; lasty = ay;
		smoothx = ax - x2;
		smoothy = ay - y2;
	}
Beispiel #26
0
///trim the patch's width in-place
void AiCarStandard::TrimPatch(Bezier & patch, float trimleft_front, float trimright_front, float trimleft_back, float trimright_back)
{
	Vec3 frontvector = (patch.GetPoint(0,3) - patch.GetPoint(0,0));
	Vec3 backvector = (patch.GetPoint(3,3) - patch.GetPoint(3,0));
	float frontwidth = frontvector.Magnitude();
	float backwidth = backvector.Magnitude();
	if (trimleft_front + trimright_front > frontwidth)
	{
		float scale = frontwidth/(trimleft_front + trimright_front);
		trimleft_front *= scale;
		trimright_front *= scale;
	}
	if (trimleft_back + trimright_back > backwidth)
	{
		float scale = backwidth/(trimleft_back + trimright_back);
		trimleft_back *= scale;
		trimright_back *= scale;
	}

	Vec3 newfl = patch.GetPoint(0,0);
	Vec3 newfr = patch.GetPoint(0,3);
	Vec3 newbl = patch.GetPoint(3,0);
	Vec3 newbr = patch.GetPoint(3,3);

	if (frontvector.Magnitude() > 0.001)
	{
		Vec3 trimdirection_front = frontvector.Normalize();
		newfl = patch.GetPoint(0,0) + trimdirection_front*trimleft_front;
		newfr = patch.GetPoint(0,3) - trimdirection_front*trimright_front;
	}

	if (backvector.Magnitude() > 0.001)
	{
		Vec3 trimdirection_back = backvector.Normalize();
		newbl = patch.GetPoint(3,0) + trimdirection_back*trimleft_back;
		newbr = patch.GetPoint(3,3) - trimdirection_back*trimright_back;
	}

	patch.SetFromCorners(newfl, newfr, newbl, newbr);
}
Beispiel #27
0
TEST_F(ChainTest, DegreeElevation) {
    EXPECT_TRUE(are_equal(wiggle, wiggle));
    Bezier Q = wiggle;
    Bezier P = Q.elevate_degree();
    EXPECT_EQ(P.size(), Q.size()+1);
    //EXPECT_EQ(0, P.forward_difference(1)[0]);
    EXPECT_TRUE(are_equal(Q, P));
    Q = wiggle;
    P = Q.elevate_to_degree(10);
    EXPECT_EQ(10, P.order());
    EXPECT_TRUE(are_equal(Q, P));
    //EXPECT_EQ(0, P.forward_difference(10)[0]);
    /*Q = wiggle.elevate_degree();
    P = Q.reduce_degree();
    EXPECT_EQ(P.size()+1, Q.size());
    EXPECT_TRUE(are_equal(Q, P));*/
}
Beispiel #28
0
Bezier subRight(Bezier bz, double t) {
    unsigned order = bz.order();
    unsigned N = order+1;
    std::valarray<Coord> row(N);
    for (unsigned i = 0; i < N; i++)
        row[i] = bz[i];

    // Triangle computation
    const double omt = (1-t);
    Bezier Right = bz;
    Right[order] = row[order];
    for (unsigned i = 1; i < N; i++) {
        for (unsigned j = 0; j < N - i; j++) {
            row[j] = omt*row[j] + t*row[j+1];
        }
        Right[order-i] = row[order-i];
    }
    return Right;
}
/** Changes the basis of p to be sbasis.
 \param p the Bernstein basis polynomial
 \returns the Symmetric basis polynomial

 if the degree is even q is the order in the symmetrical power basis,
 if the degree is odd q is the order + 1
 n is always the polynomial degree, i. e. the Bezier order
*/
void bezier_to_sbasis (SBasis & sb, Bezier const& bz)
{
    size_t n = bz.order();
    size_t q = (n+1) / 2;
    size_t even = (n & 1u) ? 0 : 1;
    sb.clear();
    sb.resize(q + even, Linear(0, 0));
    double Tjk;
    for (size_t k = 0; k < q; ++k)
    {
        for (size_t j = k; j < q; ++j)
        {
            Tjk = sgn(j, k) * binomial(n-j-k, j-k) * binomial(n, k);
            sb[j][0] += (Tjk * bz[k]);
            sb[j][1] += (Tjk * bz[n-k]); // n-j <-> [j][1]
        }
        for (size_t j = k+1; j < q; ++j)
        {
            Tjk = sgn(j, k) * binomial(n-j-k-1, j-k-1) * binomial(n, k);
            sb[j][0] += (Tjk * bz[n-k]);
            sb[j][1] += (Tjk * bz[k]);   // n-j <-> [j][1]
        }
    }
    if (even)
    {
        for (size_t k = 0; k < q; ++k)
        {
            Tjk = sgn(q,k) * binomial(n, k);
            sb[q][0] += (Tjk * (bz[k] + bz[n-k]));
        }
        sb[q][0] += (binomial(n, q) * bz[q]);
        sb[q][1] = sb[q][0];
    }
    sb[0][0] = bz[0];
    sb[0][1] = bz[n];
}
Beispiel #30
0
void Bezier::Attach(Bezier & other, bool reverse)
{
	/*if (!reverse)
	{
		//move the other patch to the location of this patch and force its
		// intermediate points into a nice grid layout
		other.SetFromCorners(other.points[0][0], other.points[0][3], points[0][0], points[0][3]);

		for (int x = 0; x < 4; x++)
		{
			//slope points in the forward direction
			Vec3 slope = other.points[0][x] - points[3][x];
			if (slope.Magnitude() > 0.0001)
				slope = slope.Normalize();

			float otherlen = (other.points[0][x] - other.points[3][x]).Magnitude();
			float mylen = (points[0][x] - points[3][x]).Magnitude();

			float meanlen = (otherlen + mylen)/2.0;
			float leglen = meanlen / 3.0;

			if (slope.Magnitude() > 0.0001)
			{
				other.points[2][x] = other.points[3][x] + slope*leglen;
				points[1][x] = points[0][x] + slope*(-leglen);
			}
			else
			{
				other.points[2][x] = other.points[3][x];
				points[1][x] = points[0][x];
			}
		}
	}*/

	//CheckForProblems();

	//store the pointer to next patch
	next_patch = &other;

	//calculate the track radius at the connection of this patch and next patch
	Vec3 a = SurfCoord(0.5,0.0);
	Vec3 b = SurfCoord(0.5,1.0);
	Vec3 c = other.SurfCoord(0.5,1.0);

	if (reverse)
	{
		a = SurfCoord(0.5,1.0);
		b = SurfCoord(0.5,0.0);
		c = other.SurfCoord(0.5,0.0);

		//Reverse();
	}

	//racing_line = a;
	Vec3 d1 = a - b;
	Vec3 d2 = c - b;
	float diff = d2.Magnitude() - d1.Magnitude();
	double dd = ((d1.Magnitude() < 0.0001) || (d2.Magnitude() < 0.0001)) ? 0.0 : d1.Normalize().dot(d2.Normalize());
	float angle = acos((dd>=1.0L)?1.0L:(dd<=-1.0L)?-1.0L:dd);
	float d1d2mag = d1.Magnitude() + d2.Magnitude();
	float alpha = (d1d2mag < 0.0001) ? 0.0f : (M_PI * diff + 2.0 * d1.Magnitude() * angle) / d1d2mag / 2.0;
	if (fabs(alpha - M_PI/2.0) < 0.001) track_radius = 10000.0;
	else track_radius = d1.Magnitude() / 2.0 / cos(alpha);
	if (d1.Magnitude() < 0.0001)
		track_curvature = 0.0;
	else
		track_curvature = 2.0 * cos(alpha) / d1.Magnitude();

	//determine it's a left or right turn at the connection
	Vec3 d = d1.cross(d2);
	if (fabs(d[0]) < 0.1 && fabs(d[1]) < 0.1 && fabs(d[2]) < 0.1)
	{
		turn = 0; //straight ahead
	}
	else if (d[1] > 0.0) turn = -1; //left turn ahead
	else turn = 1; //right turn ahead

	//calculate distance from start of the road
	if (other.next_patch == NULL || reverse) other.dist_from_start = dist_from_start + d1.Magnitude();
	length = d1.Magnitude();
}