Exemplo n.º 1
0
vec Plane::ClosestPoint(const LineSegment &lineSegment) const
{
	/*
	///@todo Output parametric d as well.
	float d;
	if (lineSegment.Intersects(*this, &d))
		return lineSegment.GetPoint(d);
	else
		if (Distance(lineSegment.a) < Distance(lineSegment.b))
			return Project(lineSegment.a);
		else
			return Project(lineSegment.b);
	*/

	assume(lineSegment.IsFinite());
	assume(!IsDegenerate());

	float aDist = Dot(normal, lineSegment.a);
	float bDist = Dot(normal, lineSegment.b);

	float denom = bDist - aDist;
	if (EqualAbs(denom, 0.f))
		return Project(Abs(aDist) < Abs(bDist) ? lineSegment.a : lineSegment.b); // Project()ing the result here is not strictly necessary,
		                                                                         // but done for numerical stability, so that Plane::Contains()
		                                                                         // will return true for the returned point.
	else
	{
		///@todo Output parametric t along the ray as well.
		float t = (d - Dot(normal, lineSegment.a)) / (bDist - aDist);
		t = Clamp01(t);
		// Project()ing the result here is necessary only if we clamped, but done for numerical stability, so that Plane::Contains() will
		// return true for the returned point.
		return Project(lineSegment.GetPoint(t));
	}
}
Exemplo n.º 2
0
static Float _ModifyHairShadowTransparencyFn(HairVideoPost* vp, Int32 oindex, HairMaterialData* mat, RayObject* ro, HairObject* op, HairGuides* guides, BaseList2D* bl, Float32* thk, VolumeData* vd, Int32 cpu, Int32 lid, Int32 seg, Int32 p, Float lined, const Vector& linep, const Vector& n, const Vector& lp, const Vector& huv, const RayHitID& ply_id, RayLight* light, Float trans)
{
	HairRenderingTag* hrt = (HairRenderingTag*)bl->GetNodeData();

	if (light)	// shadow call
		trans = (Float) 1.0 - Clamp01(((Float) 1.0 - Clamp01(trans)) * hrt->m_Shadow);
	else
		trans = (Float) 1.0 - Clamp01(((Float) 1.0 - Clamp01(trans)) * hrt->m_Trans);

	if (hrt->m_Depth > 1)
	{
		Float depth = Float(1 + (seg % hrt->m_Depth)) / Float(hrt->m_Depth);
		trans = 1.0 - ((1.0 - trans) * depth);
	}

	return trans;
}
Exemplo n.º 3
0
Arquivo: result.cpp Projeto: nodag/psa
void SaveSummary(const std::string &fname, Result &result, Config &config)
{
    const float fnorm = 2.f / sqrtf(result.npoints);
    const float rnorm = 1.f / sqrtf(2.f / (SQRT3 * result.npoints));
    
    const int csize = 512;  // Composition cell size
    const double dashes[] = { 6.0, 3.0 };
    
    cairo_surface_t *surface =
    cairo_pdf_surface_create(fname.c_str(), 2*csize, 1.5*csize);
    cairo_pdf_surface_restrict_to_version(surface, CAIRO_PDF_VERSION_1_4);
    
    cairo_t *cr = cairo_create(surface);
    unsigned char *imgdata = NULL;
    cairo_surface_t *image = NULL;
    
    // Draw points
    const float radius = 2.0;
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    for (int i = 0; i < result.points.size(); ++i) {
        float x = result.points[i].x * csize;
        float y = (1.f - result.points[i].y) * csize;
        cairo_arc(cr, x, y, radius, 0, TWOPI);
        cairo_fill(cr);
    }
    
    // Draw radial power reference level
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1);
    cairo_set_line_width(cr, 1.0);
    cairo_set_dash(cr, dashes, 2, 0);
    const float rpref = 1.f - (1.f - config.fymin) / (config.fymax - config.fymin);
    cairo_move_to(cr,   csize, csize + rpref*csize/2);
    cairo_line_to(cr, 2*csize, csize + rpref*csize/2);
    cairo_stroke(cr);
    
    // Draw radial power
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    cairo_set_line_width(cr, 1.0);
    cairo_set_dash(cr, NULL, 0, 0);
    for (int i = 0; i < result.rp.size(); ++i) {
        float x = i / (float) result.rp.size();
        float y = 1.f - (result.rp[i] - config.fymin) / (config.fymax - config.fymin);
        Clamp01(y);
        if (i == 0)
            cairo_move_to(cr, csize + x*csize, csize + y*csize/2);
        else
            cairo_line_to(cr, csize + x*csize, csize + y*csize/2);
    }
    cairo_stroke(cr);
    
    // Draw spectrum
    int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24,
                                               result.spectrum.width);
    result.spectrum.GetRGBA(imgdata);
    image = cairo_image_surface_create_for_data(imgdata, CAIRO_FORMAT_RGB24,
                                                result.spectrum.width,
                                                result.spectrum.height,
                                                stride);
    cairo_identity_matrix(cr);
    cairo_translate(cr, csize, 0);
    cairo_scale(cr, csize / (float) result.spectrum.width,
                    csize / (float) result.spectrum.height);
    cairo_set_source_surface(cr, image, 0, 0);
    cairo_paint(cr);
    
    // Draw RDF reference level
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1);
    cairo_set_line_width(cr, 1.0);
    cairo_set_dash(cr, dashes, 2, 0);
    const float rdfref = 1.f - (1.f - config.rymin) / (config.rymax - config.rymin);
    cairo_move_to(cr, 0, csize + rdfref*csize/2);
    cairo_line_to(cr, csize, csize + rdfref*csize/2);
    cairo_stroke(cr);
    
    // Draw RDF
    cairo_identity_matrix(cr);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    cairo_set_line_width(cr, 1.0);
    cairo_set_dash(cr, NULL, 0, 0);
    for (int i = 0; i < result.rdf.size(); ++i) {
        float x = i / (float) result.rdf.size();
        float y = 1.f - (result.rdf[i] - config.rymin) / (config.rymax - config.rymin);
        Clamp01(y);
        if (i == 0)
            cairo_move_to(cr, x*csize, csize + y*csize/2);
        else
            cairo_line_to(cr, x*csize, csize + y*csize/2);
    }
    cairo_stroke(cr);
    
    // Draw separators
    cairo_identity_matrix(cr);
    cairo_set_line_width(cr, 1.0);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    cairo_move_to(cr, 0, csize);
    cairo_line_to(cr, 2*csize, csize);
    cairo_stroke(cr);
    cairo_move_to(cr, csize, 0);
    cairo_line_to(cr, csize, 1.5*csize);
    cairo_stroke(cr);
    
    // Draw labels
    cairo_identity_matrix(cr);
    cairo_set_font_size(cr, 12.0);
    cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
                           CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_source_rgba(cr, 0, 0, 0, 1);
    cairo_move_to(cr, 0.0125 * csize, 1.025 * csize);
    cairo_show_text(cr, "RDF");
    cairo_stroke(cr);
    cairo_move_to(cr, 1.0125 * csize, 1.025 * csize);
    cairo_show_text(cr, "Power Spectrum");
    cairo_stroke(cr);
    
    // Draw stats box
#ifdef PSA_HAS_CGAL
    int nlines = 5;
#else
    int nlines = 4;
#endif
    nlines += (result.nsets > 1);
    double offset = 0.03;
    double bsize[] = { 0.33 * csize, (nlines * offset + 0.01) * csize };
    double banchor = 0.0125 * csize;
    cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.7);
    cairo_rectangle(cr, banchor, banchor, bsize[0], bsize[1]);
    cairo_fill(cr);
    
    // Draw stats and corresponding labels
    cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
    cairo_set_font_size(cr, 12.0);
    cairo_select_font_face(cr, "monospace", CAIRO_FONT_SLANT_NORMAL,
                           CAIRO_FONT_WEIGHT_NORMAL);
    const int len = 128;
    char label[len];
    double tanchor[2] = { 1.75 * banchor, 0.9 * banchor };
    
    int i = 1;
    if (result.nsets > 1) {
        snprintf(label, len, "Averaged over %d sets", result.nsets);
        cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize);
        cairo_show_text(cr, label);
        ++i;
    }
    snprintf(label, len, "Gbl. Mindist   %.5f", result.stats.mindist * rnorm);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);
    snprintf(label, len, "Avg. Mindist   %.5f", result.stats.avgmindist * rnorm);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);
#ifdef PSA_HAS_CGAL
    snprintf(label, len, "Orient. order  %.5f", result.stats.orientorder);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);
#endif
    snprintf(label, len, "Eff. Nyquist   %.5f", result.stats.effnyquist * fnorm);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);
    snprintf(label, len, "Oscillations   %.5f", result.stats.oscillations);
    cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i;
    cairo_show_text(cr, label);

    cairo_stroke(cr);
    
    // Save and clean up
    cairo_show_page(cr);
    cairo_surface_destroy(image);
    if (imgdata) delete[] imgdata;
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
}
Exemplo n.º 4
0
///\todo Enable this codepath. This if rom Geometric Tools for Computer Graphics,
/// but the algorithm in the book is broken and does not take into account the
/// direction of the gradient to determine the proper region of intersection.
/// Instead using a slower code path above.
/// [groupSyntax]
float3 Triangle::ClosestPoint(const LineSegment &lineSegment, float3 *otherPt) const
{
	float3 e0 = b - a;
	float3 e1 = c - a;
	float3 v_p = a - lineSegment.a;
	float3 d = lineSegment.b - lineSegment.a;

	// Q(u,v) = a + u*e0 + v*e1
	// L(t)   = ls.a + t*d
	// Minimize the distance |Q(u,v) - L(t)|^2 under u >= 0, v >= 0, u+v <= 1, t >= 0, t <= 1.

	float v_p_dot_e0 = Dot(v_p, e0);
	float v_p_dot_e1 = Dot(v_p, e1);
	float v_p_dot_d = Dot(v_p, d);

	float3x3 m;
	m[0][0] = Dot(e0, e0); m[0][1] = Dot(e0, e1); m[0][2] = -Dot(e0, d);
	m[1][0] =     m[0][1]; m[1][1] = Dot(e1, e1); m[1][2] = -Dot(e1, d);
	m[2][0] =     m[0][2]; m[2][1] =     m[1][2]; m[2][2] =  Dot(d, d);

	float3 B(-v_p_dot_e0, -v_p_dot_e1, v_p_dot_d);

	float3 uvt;
	bool success = m.SolveAxb(B, uvt);
	if (!success)
	{
		float t1, t2, t3;
		float s1, s2, s3;
		LineSegment e1 = Edge(0);
		LineSegment e2 = Edge(1);
		LineSegment e3 = Edge(2);
		float d1 = e1.Distance(lineSegment, &t1, &s1);
		float d2 = e2.Distance(lineSegment, &t2, &s2);
		float d3 = e3.Distance(lineSegment, &t3, &s3);
		if (d1 < d2 && d1 < d3)
		{
			if (otherPt)
				*otherPt = lineSegment.GetPoint(s1);
			return e1.GetPoint(t1);
		}
		else if (d2 < d3)
		{
			if (otherPt)
				*otherPt = lineSegment.GetPoint(s2);
			return e2.GetPoint(t2);
		}
		else
		{
			if (otherPt)
				*otherPt = lineSegment.GetPoint(s3);
			return e3.GetPoint(t3);
		}
	}

	if (uvt.x < 0.f)
	{
		// Clamp to u == 0 and solve again.
		float m_00 = m[2][2];
		float m_01 = -m[1][2];
		float m_10 = -m[2][1];
		float m_11 = m[1][1];
		float det = m_00 * m_11 - m_01 * m_10;
		float v = m_00 * B[1] + m_01 * B[2];
		float t = m_10 * B[1] + m_11 * B[2];
		v /= det;
		t /= det;
		if (v < 0.f)
		{
			// Clamp to v == 0 and solve for t.
			t = B[2] / m[2][2];
			t = Clamp01(t); // The solution for t must also be in the range [0,1].
			// The solution is (u,v,t)=(0,0,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a;
		}
		else if (v > 1.f)
		{
			// Clamp to v == 1 and solve for t.
			t = (B[2] - m[2][1]) / m[2][2];
			t = Clamp01(t);
			// The solution is (u,v,t)=(0,1,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return c; // == a + v*e1
		}
		else if (t < 0.f)
		{
			// Clamp to t == 0 and solve for v.
			v = B[1] / m[1][1];
//			mathassert(EqualAbs(v, Clamp01(v)));
			v = Clamp01(v); // The solution for v must also be in the range [0,1]. TODO: Is this guaranteed by the above?
			// The solution is (u,v,t)=(0,v,0).
			if (otherPt)
				*otherPt = lineSegment.a;
			return a + v * e1;
		}
		else if (t > 1.f)
		{
			// Clamp to t == 1 and solve for v.
			v = (B[1] - m[1][2]) / m[1][1];
//			mathassert(EqualAbs(v, Clamp01(v)));
			v = Clamp01(v); // The solution for v must also be in the range [0,1]. TODO: Is this guaranteed by the above?
			// The solution is (u,v,t)=(0,v,1).
			if (otherPt)
				*otherPt = lineSegment.b;
			return a + v * e1;
		}
		else
		{
			// The solution is (u,v,t)=(0,v,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a + v * e1;
		}
	}
	else if (uvt.y < 0.f)
	{
		// Clamp to v == 0 and solve again.
		float m_00 = m[2][2];
		float m_01 = -m[0][2];
		float m_10 = -m[2][0];
		float m_11 = m[0][0];
		float det = m_00 * m_11 - m_01 * m_10;
		float u = m_00 * B[0] + m_01 * B[2];
		float t = m_10 * B[0] + m_11 * B[2];
		u /= det;
		t /= det;

		if (u < 0.f)
		{
			// Clamp to u == 0 and solve for t.
			t = B[2] / m[2][2];
			t = Clamp01(t); // The solution for t must also be in the range [0,1].
			// The solution is (u,v,t)=(0,0,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a;
		}
		else if (u > 1.f)
		{
			// Clamp to u == 1 and solve for t.
			t = (B[2] - m[2][0]) / m[2][2];
			t = Clamp01(t); // The solution for t must also be in the range [0,1].
			// The solution is (u,v,t)=(1,0,t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return b;
		}
		else if (t < 0.f)
		{
			// Clamp to t == 0 and solve for u.
			u = B[0] / m[0][0];
//			mathassert(EqualAbs(u, Clamp01(u)));
			u = Clamp01(u); // The solution for u must also be in the range [0,1].
			if (otherPt)
				*otherPt = lineSegment.a;
			return a + u * e0;
		}
		else if (t > 1.f)
		{
			// Clamp to t == 1 and solve for u.
			u = (B[0] - m[0][2]) / m[0][0];
//			mathassert(EqualAbs(u, Clamp01(u)));
			u = Clamp01(u); // The solution for u must also be in the range [0,1].
			if (otherPt)
				*otherPt = lineSegment.b;
			return a + u * e0;
		}
		else
		{
			// The solution is (u, 0, t).
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a + u * e0;
		}
	}
	else if (uvt.z < 0.f)
	{
		if (otherPt)
			*otherPt = lineSegment.a;
		// Clamp to t == 0 and solve again.
		float m_00 = m[1][1];
		float m_01 = -m[0][1];
		float m_10 = -m[1][0];
		float m_11 = m[0][0];
		float det = m_00 * m_11 - m_01 * m_10;
		float u = m_00 * B[0] + m_01 * B[1];
		float v = m_10 * B[0] + m_11 * B[1];
		u /= det;
		v /= det;
		if (u < 0.f)
		{
			// Clamp to u == 0 and solve for v.
			v = B[1] / m[1][1];
			v = Clamp01(v);
			return a + v*e1;
		}
		else if (v < 0.f)
		{
			// Clamp to v == 0 and solve for u.
			u = B[0] / m[0][0];
			u = Clamp01(u);
			return a + u*e0;
		}
		else if (u+v > 1.f)
		{
			// Set v = 1-u and solve again.
//			u = (B[0] - m[0][0]) / (m[0][0] - m[0][1]);
//			mathassert(EqualAbs(u, Clamp01(u)));
//			u = Clamp01(u); // The solution for u must also be in the range [0,1].
//			return a + u*e0;

			// Clamp to v = 1-u and solve again.
			float m_00 = m[2][2];
			float m_01 = m[1][2] - m[0][2];
			float m_10 = m_01;
			float m_11 = m[0][0] + m[1][1] - 2.f * m[0][1];
			float det = m_00 * m_11 - m_01 * m_10;
			float b0 = m[1][1] - m[0][1] + v_p_dot_e1 - v_p_dot_e0;
			float b1 = -m[1][2] + v_p_dot_d;
			float u = m_00 * b0 + m_01 * b1;
			u /= det;
			u = Clamp01(u);

			float t = m_10 * b0 + m_11 * b1;
			t /= det;
			t = Clamp01(t);
			if (otherPt)
				*otherPt = lineSegment.GetPoint(t);
			return a + u*e0 + (1.f-u)*e1;
		}
		else
		{
			// The solution is (u, v, 0)
			return a + u * e0 + v * e1;
		}
	}
	else if (uvt.z > 1.f)
	{
		if (otherPt)
			*otherPt = lineSegment.b;
		// Clamp to t == 1 and solve again.
		float m_00 = m[1][1];
		float m_01 = -m[0][1];
		float m_10 = -m[1][0];
		float m_11 = m[0][0];
		float det = m_00 * m_11 - m_01 * m_10;
		float u = m_00 * (B[0]-m[0][2]) + m_01 * (B[1]-m[1][2]);
		float v = m_10 * (B[0]-m[0][2]) + m_11 * (B[1]-m[1][2]);
		u /= det;
		v /= det;
		if (u < 0.f)
		{
			// Clamp to u == 0 and solve again.
			v = (B[1] - m[1][2]) / m[1][1];
			v = Clamp01(v);
			return a + v*e1;
		}
		else if (u > 1.f)
		{
			// Clamp to u == 1 and solve again.
			v = (B[1] - m[1][0] - m[1][2]) / m[1][1];
			v = Clamp01(v); // The solution for v must also be in the range [0,1]. TODO: Is this guaranteed by the above?
			// The solution is (u,v,t)=(1,v,1).
			return a + e0 + v*e1;
		}
		else if (u+v > 1.f)
		{
			// Set v = 1-u and solve again.

			// Q(u,1-u) = a + u*e0 + e1 - u*e1 = a+e1 + u*(e0-e1)
			// L(1)   = ls.a + t*d = ls.b
			// Minimize the distance |Q(u,1-u) - L(1)| = |a+e1+ls.b + u*(e0-e1)|

			// |K + u*(e0-e1)|^2 = (K,K) + 2*u(K,e0-e1) + u^2 * (e0-e1,e0-e1)

			// grad = 2*(K,e0-e1) + 2*u*(e0-e1,e0-e1) == 0
			//                                      u == (K,e1-e0) / (e0-e1,e0-e1)

			u = (B[0] - m[0][1] - m[0][2]) / (m[0][0] - m[0][1]);
//			u = Dot(a + e1 + lineSegment.b, e1 - e0) / Dot(e0-e1, e0-e1);

//			mathassert(EqualAbs(u, Clamp01(u)));
			u = Clamp01(u);
			return a + u*e0 + (1-u)*e1;
		}
		else
		{
			// The solution is (u, v, 1)
			return a + u*e0 + v*e1;
		}
	}
	else if (uvt.x + uvt.y > 1.f)
	{
		// Clamp to v = 1-u and solve again.
		float m_00 = m[2][2];
		float m_01 = m[1][2] - m[0][2];
		float m_10 = m_01;
		float m_11 = m[0][0] + m[1][1] - 2.f * m[0][1];
		float det = m_00 * m_11 - m_01 * m_10;
		float b0 = m[1][1] - m[0][1] + v_p_dot_e1 - v_p_dot_e0;
		float b1 = -m[1][2] + v_p_dot_d;
		float u = m_00 * b0 + m_01 * b1;
		float t = m_10 * b0 + m_11 * b1;
		u /= det;
		t /= det;

		t = Clamp01(t);
		if (otherPt)
			*otherPt = lineSegment.GetPoint(t);

		if (u < 0.f)
		{
			// The solution is (u,v,t)=(0,1,t)
			return c;
		}
		if (u > 1.f)
		{
			// The solution is (u,v,t)=(1,0,t)
			return b;
		}
		mathassert(t >= 0.f);
		mathassert(t <= 1.f);
		return a + u*e0 + (1.f-u)*e1;
	}
	else // All parameters are within range, so the triangle and the line segment intersect, and the intersection point is the closest point.
	{
		if (otherPt)
			*otherPt = lineSegment.GetPoint(uvt.z);
		return a + uvt.x * e0 + uvt.y * e1;
	}
}