void Pathgrid::addEdge(CSMWorld::CommandMacro& commands, const CSMWorld::Pathgrid& source, unsigned short node1, unsigned short node2) { CSMWorld::IdTree* model = dynamic_cast<CSMWorld::IdTree*>(mData.getTableModel( CSMWorld::UniversalId::Type_Pathgrids)); int recordIndex = mPathgridCollection.getIndex(mId); int parentColumn = mPathgridCollection.findColumnIndex(CSMWorld::Columns::ColumnId_PathgridEdges); int edge0Column = mPathgridCollection.searchNestedColumnIndex(parentColumn, CSMWorld::Columns::ColumnId_PathgridEdge0); int edge1Column = mPathgridCollection.searchNestedColumnIndex(parentColumn, CSMWorld::Columns::ColumnId_PathgridEdge1); QModelIndex parent = model->index(recordIndex, parentColumn); int row = static_cast<int>(source.mEdges.size()); if (edgeExists(source, node1, node2) == -1) { commands.push(new CSMWorld::AddNestedCommand(*model, mId, row, parentColumn)); commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge0Column, parent), node1)); commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge1Column, parent), node2)); ++row; } if (edgeExists(source, node2, node1) == -1) { commands.push(new CSMWorld::AddNestedCommand(*model, mId, row, parentColumn)); commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge0Column, parent), node2)); commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge1Column, parent), node1)); } }
// subdivide the 3 lateral faces of each prism static void phase1(GRegion *gr, MVertexRTree &pos, std::set<std::pair<MVertex*, MVertex*> > &edges) { ExtrudeParams *ep = gr->meshAttributes.extrude; GFace *from = gr->model()->getFaceByTag(std::abs(ep->geo.Source)); if(!from) return; for(unsigned int i = 0; i < from->triangles.size(); i++){ for(int j = 0; j < ep->mesh.NbLayer; j++) { for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) { std::vector<MVertex*> v; if(getExtrudedVertices(from->triangles[i], ep, j, k, pos, v) == 6){ #if 0 // old if(!edgeExists(v[0], v[4], edges)) createEdge(v[1], v[3], edges); if(!edgeExists(v[4], v[2], edges)) createEdge(v[1], v[5], edges); if(!edgeExists(v[3], v[2], edges)) createEdge(v[0], v[5], edges); #else // new from Michel Benhamou if(v[1] < v[0]) createEdge(v[1], v[3], edges); else createEdge(v[0], v[4], edges); if(v[1] < v[2]) createEdge(v[1], v[5], edges); else createEdge(v[4], v[2], edges); if(v[0] < v[2]) createEdge(v[0], v[5], edges); else createEdge(v[3], v[2], edges); #endif } } } } }
int Graph::getCost(int node1, int node2) { int index = edgeExists(node1, node2); if(index =! -1) return adjList[node1].edgeList[index].cost; else return -1; }
virtual void generateEdges(unsigned int edgeSetSize) { for(unsigned int i = 0; i < vertices.size(); ++i) { auto res = kdtree.kNearest(vertices[i], edgeSetSize+1); for(const auto endVertex : res.elements) { if(edgeExists(i, endVertex->id)) { continue; } double cost = AbstractState::evaluateDistance(vertices[i]->state, endVertex->state); if(cost == 0) { continue; } AbstractEdge edgeCandidate = agent.generateAbstractEdge(vertices[i]->state, endVertex->state); if(edgeCandidate.size() != 0) { collisionChecks++; } if(edgeCandidate.size() == 0 || workspace.safeAbstractEdge(agent, edgeCandidate, collisionCheckDT)) { edges[i][endVertex->id] = Edge(endVertex->id, cost); edges[i][endVertex->id].status = Edge::CollisionCheckingStatus::VALID; if(agent.areAbstractEdgesSymmetric()) { edges[endVertex->id][i] = Edge(i, cost); edges[endVertex->id][i].status = Edge::CollisionCheckingStatus::VALID; } } } } }
//Add an edge from node1 to node2, and from node2 to node1, with // the given cost. If the cost is < 0, throw a string exception. void Graph::addEdge(int node1, int node2, double cost) { if(cost<0) throw std::string("You provided a negative cost value. We are not breaking Physics today..."); int index = edgeExists(node1, node2); //this seems to be an elegant handling: searching one list to check existence. if(index != -1) { adjList[node1].edgeList[index].dest = node2; adjList[node1].edgeList[index].cost = cost; int other = edgeExists(node2, node1); //guaranteed a return other than -1 adjList[node2].edgeList[other].dest = node1; adjList[node2].edgeList[other].cost = cost; return; } adjList[node1].edgeList.push_back(Edge(cost, node2)); adjList[node2].edgeList.push_back(Edge(cost, node1)); }
//Remove the edge from node1 to node2, and also from node2 to node1. // If there are no such edges, then don't do anything. void Graph::removeEdge(int node1, int node2) { //TODO if(node1 < 0 || node2 < 0 || node1 >= adjList.size() || node2 >= adjList.size())//because, on average, users are stupid... return; int index = edgeExists(node1, node2); if(index!=-1) { Edge temp = adjList[node1].edgeList[index]; adjList[node1].edgeList[index] = adjList[node1].edgeList[adjList[node1].edgeList.size()-1]; adjList[node1].edgeList[adjList[node1].edgeList.size()-1] = temp; adjList[node1].edgeList.pop_back(); //very tough to tell which is more efficient: swap and pop, or erase and repopulate. The latter is more elegant of course... //adjList[node1].edgeList.erase(adjList[node1].edgeList.begin()+index); int other = edgeExists(node2, node1); Edge temp2 = adjList[node2].edgeList[other]; adjList[node2].edgeList[other] = adjList[node2].edgeList[adjList[node2].edgeList.size()-1]; adjList[node2].edgeList[adjList[node2].edgeList.size()-1] = temp; adjList[node2].edgeList.pop_back(); //adjList[node2].edgeList.erase(adjList[node2].edgeList.begin()+index); } return; }
void Pathgrid::applyRemoveEdges(CSMWorld::CommandMacro& commands) { const CSMWorld::Pathgrid* source = getPathgridSource(); if (source) { // Want to remove from end of row first std::set<int, std::greater<int> > rowsToRemove; for (size_t i = 0; i <= mSelected.size(); ++i) { for (size_t j = i + 1; j < mSelected.size(); ++j) { int row = edgeExists(*source, mSelected[i], mSelected[j]); if (row != -1) { rowsToRemove.insert(row); } row = edgeExists(*source, mSelected[j], mSelected[i]); if (row != -1) { rowsToRemove.insert(row); } } } CSMWorld::IdTree* model = dynamic_cast<CSMWorld::IdTree*>(mData.getTableModel( CSMWorld::UniversalId::Type_Pathgrids)); int parentColumn = mPathgridCollection.findColumnIndex(CSMWorld::Columns::ColumnId_PathgridEdges); std::set<int, std::greater<int> >::iterator row; for (row = rowsToRemove.begin(); row != rowsToRemove.end(); ++row) { commands.push(new CSMWorld::DeleteNestedCommand(*model, mId, *row, parentColumn)); } } }
void GraphSerializer::addEntry( QString edgeId, QString edgeData, QString incId, QString incData, QString nodeId, QString nodeData ) { if ( !nodeIdMap.contains( edgeId ) ) { nodes->push_back( createNode( edgeId, edgeData ) ); } if ( !nodeIdMap.contains( incId ) ) { nodes->push_back( createNode( incId, incData ) ); } if ( !nodeIdMap.contains( nodeId ) ) { nodes->push_back( createNode( nodeId, nodeData ) ); } Data::Edge* edge1 = new Data::Edge( edgeIdSeq, "edge data", NULL, nodes->at( nodeIdMap.value( edgeId ) ), nodes->at( nodeIdMap.value( incId ) ), types->at( 1 ), true, 2 ); if ( !edgeExists( edge1 ) ) { edgeIdSeq++; } Data::Edge* edge2 = new Data::Edge( edgeIdSeq, "edge data", NULL, nodes->at( nodeIdMap.value( incId ) ), nodes->at( nodeIdMap.value( nodeId ) ), types->at( 1 ), true, 2 ); if ( !edgeExists( edge2 ) ) { edgeIdSeq++; } }
// Meshes either a prism or a hexahedral set of mesh vertices in a Transfinite Region with an internal vertex // that is created here in the function. void meshTransfElemWithInternalVertex( GRegion *gr, std::vector<MVertex *> v, std::set< std::pair<MVertex*, MVertex*> > *boundary_diags ) { int v_size = v.size(); int n_lat_tmp; if( v_size == 6 ) n_lat_tmp = 3; else if( v_size == 8 ) n_lat_tmp = 4; else{ Msg::Error("In meshTransfElemWithInternalVertex(), number of element vertices does not equal 6 or 8."); return; } const int n_lat = n_lat_tmp; // find vertex node indices for diagonalized faces std::vector<int> n1, n2; bool found_diags = false; int n_size = 0; if( n_lat == 3 ){ n1.assign(n_lat, -1); n2.assign(n_lat, -2); n_size = 3; } else if( n_lat == 4 ){ n1.assign(n_lat+2, -1); n2.assign(n_lat+2, -1); n_size = 6; } for( int p = 0; p < n_size; p++ ){ n1[p] = -p*p-p-1; n2[p] = -p*p-p-2; if( p < n_lat || n_lat == 3 ){ if( v[p] == v[p+n_lat] || v[(p+1)%n_lat] == v[(p+1)%n_lat+n_lat] ) continue; else if( edgeExists( v[p], v[(p+1)%n_lat+n_lat], (*boundary_diags) ) ){ n1[p] = p; n2[p] = (p+1)%n_lat+n_lat; found_diags = true; } else if( edgeExists( v[p+n_lat], v[(p+1)%n_lat], (*boundary_diags) ) ){ n1[p] = p+n_lat; n2[p] = (p+1)%n_lat; found_diags = true; } } else{ int add = ( p == n_lat ) ? 0 : n_lat; if( edgeExists( v[add], v[add+2], (*boundary_diags) ) ){ n1[p] = add; n2[p] = add+2; found_diags = true; } else if( edgeExists( v[add+1], v[add+3], (*boundary_diags) ) ){ n1[p] = add+1; n2[p] = add+3; found_diags = true; } } } if( !found_diags ){ if( n_lat == 3 ) addPrism( v[0], v[1], v[2], v[3], v[4], v[5], gr ); else if( n_lat ==4 ) addHexahedron( v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], gr ); return; } // make the internal vertex std::vector<double> centroid = QtFindVertsCentroid(v); MVertex *v_int = new MVertex(centroid[0], centroid[1], centroid[2], gr); gr->mesh_vertices.push_back( v_int ); // build all pyramids/tetra for( int p = 0; p < n_lat; p++ ){ int p2 = (p+1)%n_lat; if( v[p] == v[p+n_lat] && v[p2] == v[p2+n_lat] ) continue; else if( v[p] == v[p+n_lat] || v[p2] == v[p2+n_lat] ){ MVertex *v_dup = (v[p] == v[p+n_lat]) ? v[p] : v[p2]; MVertex *v_non_dup = (v_dup == v[p]) ? v[p2] : v[p]; MVertex *v_non_dup2 = (v_non_dup == v[p]) ? v[p+n_lat] : v[p2+n_lat]; addTetrahedron( v_dup, v_non_dup, v_non_dup2, v_int, gr); } else if( n1[p] == p || n2[p] == p ){ addTetrahedron( v[p], v[p2], v[p2+n_lat], v_int, gr ); addTetrahedron( v[p], v[p2+n_lat], v[p+n_lat], v_int, gr ); } else if( n1[p] == p+n_lat || n2[p] == p+n_lat ){ addTetrahedron( v[p], v[p2], v[p+n_lat], v_int, gr ); addTetrahedron( v[p2], v[p2+n_lat], v[p+n_lat], v_int, gr ); } else addPyramid( v[p], v[p2], v[p2+n_lat], v[p+n_lat], v_int, gr ); } if( n_lat == 3){ // bottom and top addTetrahedron( v[0], v[1], v[2], v_int, gr ); addTetrahedron( v[3], v[5], v[4], v_int, gr ); } else if( n_lat == 4 ){ for( int p = 4; p < 6; p++ ){ int add = (p == 4) ? 0 : 4; if( n1[p] == 0+add || n2[p] == 0+add ){ addTetrahedron( v[add], v[1+add], v[2+add], v_int, gr ); addTetrahedron( v[add], v[2+add], v[3+add], v_int, gr ); } else if( n1[p] == 1+add || n2[p] == 1+add ){ addTetrahedron( v[1+add], v[2+add], v[3+add], v_int, gr ); addTetrahedron( v[1+add], v[3+add], v[add], v_int, gr ); } else addPyramid( v[add], v[1+add], v[2+add], v[3+add], v_int, gr ); } } } // End of meshTransfiniteWithInternalVertex()
/************************************************************ * Basic const ops ***********************************************************/ EdgeId PoseGraph::nextEdgeId() { while (edgeExists(_nextEdgeId)) _nextEdgeId++; return _nextEdgeId; }
// create tets static void phase3(GRegion *gr, MVertexRTree &pos, std::set<std::pair<MVertex*, MVertex*> > &edges) { ExtrudeParams *ep = gr->meshAttributes.extrude; GFace *from = gr->model()->getFaceByTag(std::abs(ep->geo.Source)); if(!from) return; for(unsigned int i = 0; i < from->triangles.size(); i++){ MTriangle* tri = from->triangles[i]; for(int j = 0; j < ep->mesh.NbLayer; j++) { for(int k = 0; k < ep->mesh.NbElmLayer[j]; k++) { std::vector<MVertex*> v; if(getExtrudedVertices(tri, ep, j, k, pos, v) == 6){ if(edgeExists(v[3], v[1], edges) && edgeExists(v[4], v[2], edges) && edgeExists(v[3], v[2], edges)) { createTet(v[0], v[1], v[2], v[3], gr, tri); createTet(v[3], v[4], v[5], v[2], gr, tri); createTet(v[1], v[3], v[4], v[2], gr, tri); } else if(edgeExists(v[3], v[1], edges) && edgeExists(v[1], v[5], edges) && edgeExists(v[3], v[2], edges)) { createTet(v[0], v[1], v[2], v[3], gr, tri); createTet(v[3], v[4], v[5], v[1], gr, tri); createTet(v[3], v[1], v[5], v[2], gr, tri); } else if(edgeExists(v[3], v[1], edges) && edgeExists(v[1], v[5], edges) && edgeExists(v[5], v[0], edges)) { createTet(v[0], v[1], v[2], v[5], gr, tri); createTet(v[3], v[4], v[5], v[1], gr, tri); createTet(v[1], v[3], v[5], v[0], gr, tri); } else if(edgeExists(v[4], v[0], edges) && edgeExists(v[4], v[2], edges) && edgeExists(v[3], v[2], edges)) { createTet(v[0], v[1], v[2], v[4], gr, tri); createTet(v[3], v[4], v[5], v[2], gr, tri); createTet(v[0], v[3], v[4], v[2], gr, tri); } else if(edgeExists(v[4], v[0], edges) && edgeExists(v[4], v[2], edges) && edgeExists(v[5], v[0], edges)) { createTet(v[0], v[1], v[2], v[4], gr, tri); createTet(v[3], v[4], v[5], v[0], gr, tri); createTet(v[0], v[2], v[4], v[5], gr, tri); } else if(edgeExists(v[4], v[0], edges) && edgeExists(v[1], v[5], edges) && edgeExists(v[5], v[0], edges)) { createTet(v[0], v[1], v[2], v[5], gr, tri); createTet(v[3], v[4], v[5], v[0], gr, tri); createTet(v[0], v[1], v[4], v[5], gr, tri); } } } } } }