// 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; }
/// // 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; }
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); }
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; }