// pyramid
number CalculateVolumePyramid(const vector3& a, const vector3& b,
		const vector3& c, const vector3& d, const vector3& e) {
	number result = 0;
//	UG_LOG("a: " << a << " b: " << b << " c: " << c << " d: " << d << " e: " << e << endl)
	//fixme check for a set of volumes that this condition is met!
	// check a,b,c,d are in same plane
	// fixme why does this check only work in x,y plane?!
//	vector3 r, n, x;
//	VecCross(n, a, b);
//	VecNormalize(n, n);
//
//	VecSubtract(r, a, b);
//	VecSubtract(x, c, r);
//	number dot = VecDot(x, n);
//
//	UG_LOG("dot pyra: " << dot<< endl)
//	UG_ASSERT(dot < SMALL,
//			"pyramid volume calculation needs all base are points in one plane!");

	vector3 center, h_, h, c1, c2, da, ba, cb, cd;
	VecSubtract(da, d, a);
	VecSubtract(ba, b, a);
	VecSubtract(cb, c, b);
	VecSubtract(cd, c, d);
	VecCross(c1, da, ba);
	VecCross(c2, cb, cd);
	number A = 0.5 * VecLength(c1) + 0.5 * VecLength(c2);
//	UG_LOG("A pyra: " << A <<endl)

	vector3 arr[] = { a, b, c, d };
	CalculateCenter(center, arr, 4);

	number height = DistancePointToPlane(e, center, c1);

//	VecSubtract(h_, e, center);
//	VecAdd(h, h_, center);
//	VecSubtract(h, e, center);
//	 VecLength(h);
//	UG_LOG("pyra h: " << height << endl)

	result = 1.0 / 3.0 * A * height;
//	UG_LOG("pyra vol: " << result << endl)

	return result;
}
Beispiel #2
0
///
//	TriangleBoxIntersection()
//
//		Determine if a bounding box and triangle intersect
//
bool TriangleBoxIntersection(const MathVector<3>& p0, const MathVector<3>& p1,
							 const MathVector<3>& p2,
							 const MathVector<3>& boxMin, const MathVector<3>& boxMax)
{
	vector3 Trans;
	vector3 Scale(1.0, 1.0, 1.0);
	vector3 TransMax;
	TRI		TestTri;

	///
	//	Compute the scale and transform required to make BBox
	//	a voxel
	//
	Trans.x() = (boxMax.x() + boxMin.x()) / 2;
	Trans.y() = (boxMax.y() + boxMin.y()) / 2;
	Trans.z() = (boxMax.z() + boxMin.z()) / 2;

	VecSubtract(TransMax, boxMax, Trans);
	
	if(TransMax.x() != 0)
		Scale.x() = 0.5f / TransMax.x();
	if(TransMax.y() != 0)
		Scale.y() = 0.5f / TransMax.y();
	if(TransMax.z() != 0)
		Scale.z() = 0.5f / TransMax.z();

	///
	//	Put the triangle in voxel space
	//	
	TestTri.m_P[0].x() = (p0.x() - Trans.x()) * Scale.x();
	TestTri.m_P[0].y() = (p0.y() - Trans.y()) * Scale.y();
	TestTri.m_P[0].z() = (p0.z() - Trans.z()) * Scale.z();

	TestTri.m_P[1].x() = (p1.x() - Trans.x()) * Scale.x();
	TestTri.m_P[1].y() = (p1.y() - Trans.y()) * Scale.y();
	TestTri.m_P[1].z() = (p1.z() - Trans.z()) * Scale.z();
	
	TestTri.m_P[2].x() = (p2.x() - Trans.x()) * Scale.x();
	TestTri.m_P[2].y() = (p2.y() - Trans.y()) * Scale.y();
	TestTri.m_P[2].z() = (p2.z() - Trans.z()) * Scale.z();

	///
	//	Test against the voxel
	//
	return(TriCubeIntersection(TestTri) == INSIDE);	
}
D3DMATRIX* MatrixLookAtLH( 
    D3DMATRIX *pOut, 
    const D3DVECTOR *pEye, 
    const D3DVECTOR *pAt,
    const D3DVECTOR *pUp 
    )
{

    D3DVECTOR vecX, vecY, vecZ;

    // Compute direction of gaze. (+Z)

    VecSubtract(&vecZ, pAt, pEye);
    VecNormalize(&vecZ, &vecZ);

    // Compute orthogonal axes from cross product of gaze and pUp vector.
    VecCross(&vecX, pUp, &vecZ);
    VecNormalize(&vecX, &vecX);
    VecCross(&vecY, &vecZ, &vecX);

    // Set rotation and translate by pEye
    pOut->_11 = vecX.x;
    pOut->_21 = vecX.y;
    pOut->_31 = vecX.z;
    pOut->_41 = -VecDot(&vecX, pEye);

    pOut->_12 = vecY.x;
    pOut->_22 = vecY.y;
    pOut->_32 = vecY.z;
    pOut->_42 = -VecDot(&vecY, pEye);

    pOut->_13 = vecZ.x;
    pOut->_23 = vecZ.y;
    pOut->_33 = vecZ.z;
    pOut->_43 = -VecDot(&vecZ, pEye);

    pOut->_14 = 0.0f;
    pOut->_24 = 0.0f;
    pOut->_34 = 0.0f;
    pOut->_44 = 1.0f;

    return pOut;
}
Beispiel #4
0
void OrderDownwindForDofDist(SmartPtr<DoFDistribution> dd, ConstSmartPtr<TDomain> domain,
		SmartPtr<UserData<MathVector<TDomain::dim>, TDomain::dim> > spVelocity,
		number time, int si, number threshold)
{
	static const int dim = TDomain::dim;
	const size_t num_ind = dd->num_indices();
	typedef typename std::pair<MathVector<dim>, size_t> pos_type;
	typedef typename std::vector<std::vector<size_t> > adjacency_type;

	//	get positions of indices
	typename std::vector<pos_type> vPositions;
	ExtractPositions(domain, dd, vPositions);

	// get adjacency vector of vectors
	adjacency_type vvConnections;
	dd->get_connections(vvConnections);

	// Check vector sizes match
	if (vvConnections.size() != num_ind)
		UG_THROW("OrderDownstreamForDofDist: "
				"Adjacency list of dimension " << num_ind << " expected, got "<< vvConnections.size());

	if (vPositions.size() != num_ind)
		UG_THROW("OrderDownstreamForDofDist: "
				"Position list of dimension " << num_ind << " expected, got "<< vPositions.size());

	// init helper structures
	std::vector<size_t> vNewIndex(num_ind, 0);
	std::vector<size_t> vAncestorsCount(num_ind, 0);
	std::vector<bool> vVisited(num_ind, false);

	// remove connections that are not in stream direction
	adjacency_type::iterator VertexIter;
	std::vector<size_t>::iterator AdjIter;
	std::vector<size_t> vAdjacency;

	// count how many vertex were kept / removed per adjacency vector
	size_t initialcount, kept, removed = 0;

	MathVector<TDomain::dim> vVel1, vPos1, vPos2, vDir1_2;
	size_t i;
	for (VertexIter = vvConnections.begin(), i=0; VertexIter != vvConnections.end(); VertexIter++, i++)
	{
		UG_DLOG(LIB_DISC_ORDER, 2, "Filtering vertex " << i << " adjacency vector." <<std::endl);
		initialcount = VertexIter->size();
		kept = 0;
		removed = 0;
		// get position and velocity of first trait
		vPos1 = vPositions.at(i).first;
		(*spVelocity)(vVel1, vPos1, time, si);
		if (VecLengthSq(vVel1) == 0 )
		{
			// if the velocity is zero at this trait it does not interfere with others
			// NOTE: otherwise this trait would be downwind-connected to all of it's neighbors
			// NOTE: VertexIter-> will access inner vector functions (*VertexIter) is the inner vector.
			removed = VertexIter->size();
			VertexIter->clear();
		}
		else {
			AdjIter = VertexIter->begin();
			while (AdjIter != VertexIter->end())
			{
				// get position of second trait
				vPos2 = vPositions.at(*AdjIter).first;

				// get difference vector as direction vector
				VecSubtract(vDir1_2, vPos2, vPos1);

				// compute angle between velocity and direction vector
				number anglex1_2 = VecAngle(vDir1_2, vVel1);

				// if angle is smaller then threshold continue else remove connection
				if (anglex1_2 <= threshold && i != *AdjIter)
				{
					vAncestorsCount.at(*AdjIter) += 1;
					++AdjIter;
					kept++;
				} else {
					AdjIter = VertexIter->erase(AdjIter);
					removed++;
				}
			}
		}
		UG_DLOG(LIB_DISC_ORDER, 2, "Kept: " << kept << ", removed: " << removed << " of " << initialcount
				<< " entries in adjacency matrix." << std::endl << std::endl);
	}
	// calculate downwindorder
	// Find vertexes without any ancestors and start NumeriereKnoten on them.
	size_t v,N;
	for (v=0, N=0; v < vvConnections.size(); v++)
	{
		if (vAncestorsCount[v] == 0 && !vVisited[v])
		{
			NumeriereKnoten(vvConnections, vVisited, vAncestorsCount, vNewIndex, N, v);
		}
	}

	// sanity check
	if (N < vvConnections.size()){
		size_t fails = 0;
		for (v=0; v < vvConnections.size(); v++) {
			if (!vVisited[v]) {
				UG_DLOG(LIB_DISC_ORDER, 2, v << "was not visited, has unresolved ancestors: " << vAncestorsCount[v] << std::endl);
				fails ++;
			}
		}
		UG_THROW("OrderDownwindForDist failed, " << fails << " traits unvisited." << std::endl);
	}

	//	reorder traits
	dd->permute_indices(vNewIndex);
}
Beispiel #5
0
bool AdaptSurfaceGridToCylinder(Selector& selOut, Grid& grid,
                                Vertex* vrtCenter, const vector3& normal,
                                number radius, number rimSnapThreshold,  AInt& aInt,
                                APosition& aPos)
{
    if(!grid.has_vertex_attachment(aPos)) {
        UG_THROW("Position attachment required!");
    }

    Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);

    if(rimSnapThreshold < 0)
        rimSnapThreshold = 0;

    if(rimSnapThreshold > (radius - SMALL))
        rimSnapThreshold = radius - SMALL;

    const number smallRadius = radius - rimSnapThreshold;
    const number smallRadiusSq = smallRadius * smallRadius;
    const number largeRadius = radius + rimSnapThreshold;
    const number largeRadiusSq = largeRadius * largeRadius;

//	the cylinder geometry
    vector3 axis;
    VecNormalize(axis, normal);
    vector3 center = aaPos[vrtCenter];

//	recursively select all vertices in the cylinder which can be reached from a
//	selected vertex by following an edge. Start with the given one.
//	We'll also select edges which connect inner with outer vertices. Note that
//	some vertices are considered rim-vertices (those with a distance between
//	smallRadius and largeRadius). Those are neither considered inner nor outer.
    Selector& sel = selOut;
    sel.clear();
    sel.select(vrtCenter);

    stack<Vertex*> vrtStack;
    vrtStack.push(vrtCenter);

    Grid::edge_traits::secure_container edges;
    Grid::face_traits::secure_container faces;
    vector<Quadrilateral*> quads;

    while(!vrtStack.empty()) {
        Vertex* curVrt = vrtStack.top();
        vrtStack.pop();

        //	we have to convert associated quadrilaterals to triangles.
        //	Be careful not to alter the array of associated elements while we iterate
        //	over it...
        quads.clear();
        grid.associated_elements(faces, curVrt);
        for(size_t i = 0; i < faces.size(); ++i) {
            if(faces[i]->num_vertices() == 4) {
                Quadrilateral* q = dynamic_cast<Quadrilateral*>(faces[i]);
                if(q)
                    quads.push_back(q);
            }
        }

        for(size_t i = 0; i < quads.size(); ++i) {
            Triangulate(grid, quads[i], &aaPos);
        }

        //	now check whether edges leave the cylinder and mark them accordingly.
        //	Perform projection of vertices to the cylinder rim for vertices which
        //	lie in the threshold area.
        grid.associated_elements(edges, curVrt);

        for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge) {
            Edge* e = edges[i_edge];
            Vertex* vrt = GetConnectedVertex(e, curVrt);

            if(sel.is_selected(vrt))
                continue;

            vector3 p = aaPos[vrt];
            vector3 proj;
            ProjectPointToRay(proj, p, center, axis);
            number distSq = VecDistanceSq(p, proj);

            if(distSq < smallRadiusSq) {
                sel.select(vrt);
                vrtStack.push(vrt);
            }
            else if(distSq < largeRadiusSq) {
                sel.select(vrt);
                //	cut the ray from center through p with the cylinder hull to calculate
                //	the new position of vrt.
                vector3 dir;
                VecSubtract(dir, p, center);
                number t0, t1;
                if(RayCylinderIntersection(t0, t1, center, dir, center, axis, radius))
                    VecScaleAdd(aaPos[vrt], 1., center, t1, dir);
            }
            else {
                //	the edge will be refined later on
                sel.select(e);
            }
        }
    }

//	refine selected edges and use a special refinement callback, which places
//	new vertices on edges which intersect a cylinder on the cylinders hull.
    CylinderCutProjector refCallback(MakeGeometry3d(grid, aPos),
                                     center, axis, radius);
    Refine(grid, sel, aInt, &refCallback);

//	finally select all triangles which lie in the cylinder
    sel.clear();
    vrtStack.push(vrtCenter);
    sel.select(vrtCenter);

    while(!vrtStack.empty()) {
        Vertex* curVrt = vrtStack.top();
        vrtStack.pop();
        grid.associated_elements(faces, curVrt);

        for(size_t i_face = 0; i_face < faces.size(); ++i_face) {
            Face* f = faces[i_face];
            if(sel.is_selected(f))
                continue;

            sel.select(f);

            for(size_t i = 0; i < f->num_vertices(); ++i) {
                Vertex* vrt = f->vertex(i);
                if(!sel.is_selected(vrt)) {
                    number dist = DistancePointToRay(aaPos[vrt], center, axis);
                    if(dist < (radius - SMALL)) {
                        sel.select(vrt);
                        vrtStack.push(vrt);
                    }
                }
            }
        }
    }

    sel.clear<Vertex>();

    return true;
}