예제 #1
0
파일: Curve.cpp 프로젝트: diekev/blender
void Curve::computeCurvatureAndOrientation ()
{
	const_vertex_iterator v = vertices_begin(), vend = vertices_end(), v2, prevV, v0;
	Vec2d p0, p1, p2;
	Vec3r p;

	p = (*v)->point2d();
	p0 = Vec2d(p[0], p[1]);
	prevV = v;
	++v;
	p = (*v)->point2d();
	p1 = Vec2d(p[0], p[1]);
	Vec2d prevDir(p1 - p0);

	for (; v! = vend; ++v) {
		v2 = v;
		++v2;
		if (v2 == vend)
			break;
		Vec3r p2 = (*v2)->point2d();

		Vec2d BA = p0 - p1;
		Vec2d BC = p2 - p1;
		real lba = BA.norm(), lbc = BC.norm();
		BA.normalizeSafe();
		BC.normalizeSafe();
		Vec2d normalCurvature = BA + BC;
		Vec2d dir = Vec2d(BC - BA);
		Vec2d normal = Vec2d(-dir[1], dir[0]);

		normal.normalizeSafe();
		real curvature = normalCurvature * normal;
		if (lba + lbc > MY_EPSILON)
			curvature /= (0.5 * lba + lbc);
		if (dir.norm() < MY_EPSILON)
			dir = 0.1 * prevDir;
		(*v)->setCurvatureFredo(curvature);
		(*v)->setDirectionFredo(dir);

		prevV = v;
		p0 = p1;
		p1 = p2;
		prevDir = dir;
		prevDir.normalize();
	}
	(*v)->setCurvatureFredo((*prevV)->curvatureFredo());
	(*v)->setDirectionFredo((*v)->point2d() - (*prevV)->point2d());
	v0 = vertices_begin();
	v2 = v0;
	++v2;
	(*v0)->setCurvatureFredo((*v2)->curvatureFredo());
	(*v0)->setDirectionFredo((*v2)->point2d() - (*v0)->point2d());

	//closed curve case one day...

	//
	return;

	//numerical degeneracy verification... we'll see later
	const_vertex_iterator vLastReliable = vertices_begin();

	v = vertices_begin();
	p = (*v)->point2d();
	p0 = Vec2d(p[0], p[1]);
	prevV = v;
	++v;
	p = (*v)->point2d();
	p1 = Vec2d(p[0], p[1]);
	bool isReliable = false;
	if ((p1 - p0).norm > EPS_CURVA) {
		vLastReliable = v;
		isReliable = true;
	}

	for (; v != vend; ++v) {
		v2 = v;
		++v2;
		if (v2 == vend)
			break;
		Vec3r p2 = (*v2)->point2d();

		Vec2d BA = p0 - p1;
		Vec2d BC = p2 - p1;
		real lba = BA.norm(), lbc = BC.norm();

		if ((lba + lbc) < EPS_CURVA) {
			isReliable = false;
			cerr << "/";
		}
		else {
			if (!isReliable) {  //previous points were not reliable
				const_vertex_iterator vfix = vLastReliable;
				++vfix;
				for (; vfix != v; ++vfix) {
					(*vfix)->setCurvatureFredo((*v)->curvatureFredo());
					(*vfix)->setDirectionFredo((*v)->directionFredo());
				}
			}
			isReliable = true;
			vLastReliable = v;
		}
		prevV = v;
		p0 = p1;
		p1 = p2;
	}
}
예제 #2
0
static std::vector<Vec2d> make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip)
{
    std::vector<Vec2d> points;
    double dx = M_PI_4; // very coarse spacing to begin with
    double limit = std::min(2*M_PI, width);
    for (double x = 0.; x < limit + EPSILON; x += dx) {  // so the last point is there too
        x = std::min(x, limit);
        points.emplace_back(Vec2d(x,f(x, z_sin,z_cos, vertical, flip)));
    }

    // now we will check all internal points and in case some are too far from the line connecting its neighbours,
    // we will add one more point on each side:
    const double tolerance = .1;
    for (unsigned int i=1;i<points.size()-1;++i) {
        auto& lp = points[i-1]; // left point
        auto& tp = points[i];   // this point
        Vec2d lrv = tp - lp;
        auto& rp = points[i+1]; // right point
        // calculate distance of the point to the line:
        double dist_mm = unscale<double>(scaleFactor) * std::abs(cross2(rp, lp) - cross2(rp - lp, tp)) / lrv.norm();
        if (dist_mm > tolerance) {                               // if the difference from straight line is more than this
            double x = 0.5f * (points[i-1](0) + points[i](0));
            points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip)));
            x = 0.5f * (points[i+1](0) + points[i](0));
            points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip)));
            // we added the points to the end, but need them all in order
            std::sort(points.begin(), points.end(), [](const Vec2d &lhs, const Vec2d &rhs){ return lhs < rhs; });
            // decrement i so we also check the first newly added point
            --i;
        }
    }
    return points;
}