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); }
/************* * DESCRIPTION: - * INPUT: pointer to chunk * OUTPUT: - *************/ static void ParseNamedObject(HANDLER_DATA *data, CHUNK *mainchunk) { CHUNK chunk; TRIANGLE *triangle; TRILIST *ph1,*ph2; float angle; UWORD p1, p2, p3; UWORD *edges; int i, h; ReadASCIIZ(data, data->ObjName); do { BeginChunk(data, &chunk); switch (chunk.id) { case ID_TRIANGLE: ParseTriObject(data, &chunk); break; } EndChunk(data, &chunk); } while (INCHUNK); if (data->TriList && (data->link->type == LINK_RENDERER)) { // go through all vertices and calculate normals (only for renderer) for (i = 0; i < data->pointcount; i++) { data->VertNorms[i].x = data->VertNorms[i].y = data->VertNorms[i].z = 0.f; ph1 = data->TriList[i]; while (ph1) { for (ph2 = ph1->next; ph2 != NULL; ph2 = ph2->next) { if (!ph1->flag || !ph2->flag) { // test angle between two triangles angle = VecAngle(data->TriNorms[ph1->tri], data->TriNorms[ph2->tri]); // if (angle < 2*PI && angle > /*cos_*/smooth_angle) if (angle >0 && angle < /*cos_*/data->smooth_angle) { if (!ph1->flag) { VecAdd(&data->VertNorms[i], &data->TriNorms[ph1->tri], &data->VertNorms[i]); ph1->flag = TRUE; data->TriSmooth[ph1->tri] = TRUE; } if (!ph2->flag) { VecAdd(&data->VertNorms[i], &data->TriNorms[ph2->tri], &data->VertNorms[i]); ph2->flag = TRUE; data->TriSmooth[ph2->tri] = TRUE; } } } } ph2 = ph1; ph1 = ph1->next; delete ph2; } VecNormalize(&data->VertNorms[i]); } } if (data->face) { data->link->ObjectBegin(data->rc); data->defaultsurface = data->link->SurfaceAdd(data->rc); if (!data->defaultsurface) { data->err = ERR_MEM; return; } data->link->SurfaceName(data->rc, data->defaultsurface, "default"); data->link->SurfaceDiffuse(data->rc, data->defaultsurface, 0.9f, 0.9f, 0.9f); data->link->SurfaceAmbient(data->rc, data->defaultsurface, 0.1f, 0.1f, 0.1f); data->link->SurfaceRefPhong(data->rc, data->defaultsurface, 49.f); triangle = data->link->TriangleAdd(data->rc, data->facecount,data->defaultsurface,data->mainactor); if (!triangle) { data->err = ERR_MEM; return; } if (data->link->type == LINK_SCENARIO) { // modeler needs points,edges and faces seperate if (data->link->TriangleAddPoints(data->rc, data->pointcount,data->points) == -1) { data->err = ERR_MEM; return; } edges = new UWORD[data->facecount*6]; if (!edges) { data->err = ERR_MEM; return; } for (i = 0; i < data->facecount; i++) { h = i*6; edges[h++] = data->face[i].p1; edges[h++] = data->face[i].p2; edges[h++] = data->face[i].p2; edges[h++] = data->face[i].p3; edges[h++] = data->face[i].p3; edges[h++] = data->face[i].p1; } if (data->link->TriangleAddEdges(data->rc, data->facecount*3,edges) == -1) { delete edges; data->err = ERR_MEM; return; } delete edges; } for (i = 0; i < data->facecount; i++) { p1 = data->face[i].p1; p2 = data->face[i].p3; p3 = data->face[i].p2; if(data->replacesurface) data->link->TriangleSurface(data->rc, triangle, data->replacesurface); else { if(!data->material[i]) data->link->TriangleSurface(data->rc, triangle, data->defaultsurface); else data->link->TriangleSurface(data->rc, triangle, data->material[i]); } if (data->link->type == LINK_SCENARIO) { // modeler needs edges data->link->TriangleSetEdges(data->rc, triangle,i*3,i*3+1,i*3+2); } else { // raystorm renderer needs triangles and normals data->link->TrianglePoints(data->rc, triangle,&data->points[p1],&data->points[p2],&data->points[p3]); if (!VecZero(data->TriNorms[i])) { // generate smooth triangle when smooth flag is set if (data->TriSmooth[i]) { data->link->TriangleVNorm(data->rc, triangle, VecZero(data->VertNorms[p1]) ? &data->TriNorms[i] : &data->VertNorms[p1], VecZero(data->VertNorms[p2]) ? &data->TriNorms[i] : &data->VertNorms[p2], VecZero(data->VertNorms[p3]) ? &data->TriNorms[i] : &data->VertNorms[p3]); } } if(data->mapping) { data->link->TriangleUV(data->rc, triangle, &data->mapping[p1], &data->mapping[p2], &data->mapping[p3]); } } // next triangle triangle = data->link->TriangleGetNext(data->rc, triangle); } data->link->ObjectEnd(data->rc); } CleanupMesh(data); }