bool CconnectClusterPlanar::preProcess(ClusterGraph &C,Graph &G) { if (!isCConnected(C)) { m_errorCode = nonCConnected; return false; } if (!isPlanar(C)) { m_errorCode = nonPlanar; return false; } cluster c; SListPure<node> selfLoops; makeLoopFree(G,selfLoops); c = C.rootCluster(); bool cPlanar = planarityTest(C,c,G); return cPlanar; }
void Planar::reloadFile(string configFile) throw(FileNotFound) { ifstream fin(configFile); if (!fin.is_open()) { throw FileNotFound(configFile + " is missing and cannot be loaded."); } //Determine the number of vertices fin >> total; //Gather each of the vertices for(int i = 0; i < total; ++i) { glm::vec3 pt; fin >> pt.x; fin >> pt.y; fin >> pt.z; vertices.push_back(pt); } //Check for convexity convex = isConvex(); //Check for planarity planar = isPlanar(); //Build the geometry buildGeometry(); //Put all of the vertices into an array mesh.dump(); //Allocate the buffer space Geometry::buildBuffer(mesh.total, mesh.colors, mesh.normals, mesh.points); }
void SimpleEmbedder::call(Graph& G, adjEntry& adjExternal) { OGDF_ASSERT(isPlanar(G)); //---------------------------------------------------------- // // determine embedding of G // // We currently compute any embedding and choose the maximal face // as external face // if we use FixedEmbeddingInserterOld, we have to re-use the computed // embedding, otherwise crossing nodes can turn into "touching points" // of edges (alternatively, we could compute a new embedding and // finally "remove" such unnecessary crossings). adjExternal = nullptr; if(!G.representsCombEmbedding()) planarEmbed(G); if (G.numberOfEdges() > 0) { CombinatorialEmbedding E(G); //face fExternal = E.maximalFace(); face fExternal = findBestExternalFace(G, E); adjExternal = fExternal->firstAdj(); } }
void TriMeshPlanar::postInitialSetup() { // works for non-parallel mesh only if(!isPlanar()) error->all(FLERR,"Face defined as planar face is in fact not planar. You might want to check the 'curvature' setting"); if(this->isParallel()) error->all(FLERR,"internal error"); buildEdgeLists(); }
bool InnerRegion::isValid(){ // Is planar bool valid = isPlanar(); // All vertices (internal and boundary) must be dominated by the two endpoints for (int i = 0; i < getSize(); i++) { if (i == endpoint1 || i == endpoint2) { continue; } valid &= isAdjacent(i, endpoint1) || isAdjacent(i, endpoint2); } return valid; }
// sets the positions of the nodes in a largest face of G in the form // of a regular k-gon. The corresponding nodes and their positions are // stored in nodes and pos, respectively. void TutteLayout::setFixedNodes( const Graph &G, List<node>& nodes, List<DPoint>& pos, double radius) { // compute faces of a copy of G GraphCopy GC(G); // compute a planar embedding if \a G is planar if(isPlanar(G)) planarEmbed(GC); //FIXME this stuff above seems wrong!! CombinatorialEmbedding E(GC); E.computeFaces(); // search for largest face face maxFace = E.maximalFace(); // delete possible old entries in nodes and pos nodes.clear(); pos.clear(); // set nodes and pos NodeArray<bool> addMe(GC,true); List<node> maxNodes; for(adjEntry adj : maxFace->entries) { maxNodes.pushBack(adj->theNode()); } for(node w : maxNodes) { if(addMe[w]) { nodes.pushBack(w); addMe[w] = false; } } double step = 2.0 * Math::pi / (double)(nodes.size()); double alpha = 0.0; for(int i = 0; i < nodes.size(); ++i) { pos.pushBack(DPoint(radius * cos(alpha), radius * sin(alpha))); alpha += step; } }
void AudioResampleImpl::splitAudioData(AudioData & data, boost::scoped_array<char*> & split) const { auto dataFormat = data.format(); if (dataFormat.isPlanar()) { /// Для планарного формата необходимо представить данные из result const int numChannels = dataFormat.channelCount(); split.reset(new char*[numChannels]); split_ref(data.begin(), data.end(), data.numBytes() / numChannels, split.get()); } else { /// Interleaved данные помещаются в один массив split.reset(new char*[1]); split[0] = data.data(); } }
void UpwardPlanarSubgraphSimple::call(GraphCopy &GC, List<edge> &delEdges) { const Graph &G = GC.original(); delEdges.clear(); // We construct an auxiliary graph H which represents the current upward // planar subgraph. Graph H; NodeArray<node> mapToH(G,nullptr); NodeArray<node> mapToG(H,nullptr); for(node v : G.nodes) mapToG[ mapToH[v] = H.newNode() ] = v; // We currently support only single-source acyclic digraphs ... node s; hasSingleSource(G,s); OGDF_ASSERT(s != 0); OGDF_ASSERT(isAcyclic(G)); // We start with a spanning tree of G rooted at the single source. NodeArray<bool> visitedNode(G,false); SListPure<edge> treeEdges; dfsBuildSpanningTree(s,treeEdges,visitedNode); // Mark all edges in the spanning tree so they can be skipped in the // loop below and add (copies of) them to H. EdgeArray<bool> visitedEdge(G,false); SListConstIterator<edge> it; for(it = treeEdges.begin(); it.valid(); ++it) { edge eG = *it; visitedEdge[eG] = true; H.newEdge(mapToH[eG->source()],mapToH[eG->target()]); } // Add subsequently the remaining edges to H and test if the resulting // graph is still upward planar. If not, remove the edge again from H // and add it to delEdges. SList<Tuple2<node,node> > augmented; GraphCopySimple graphAcyclicTest(G); for(edge eG : G.edges) { // already treated ? if(visitedEdge[eG] == true) continue; // insert edge into H edge eH = H.newEdge(mapToH[eG->source()],mapToH[eG->target()]); node superSink; SList<edge> augmentedEdges; if (UpwardPlanarity::upwardPlanarAugment_singleSource(H,superSink,augmentedEdges) == false) { // if H is no longer upward planar, remove eG from subgraph H.delEdge(eH); delEdges.pushBack(eG); } else { // add augmented edges as node-pair to tmpAugmented and remove // all augmented edges from H again SList<Tuple2<node,node> > tmpAugmented; SListConstIterator<edge> it; for(it = augmentedEdges.begin(); it.valid(); ++it) { node v = mapToG[(*it)->source()]; node w = mapToG[(*it)->target()]; if (v && w) tmpAugmented.pushBack(Tuple2<node,node>(v,w)); H.delEdge(*it); } if (mapToG[superSink] == nullptr) H.delNode(superSink); //**************************************************************** // The following is a simple workaround to assure the following // property of the upward planar subgraph: // The st-augmented upward planar subgraph plus the edges not // in the subgraph must be acyclic. (This is a special property // of the embedding, not the augmentation.) // The upward-planar embedding function gives us ANY upward-planar // embedding. We check if the property above holds with this // embedding. If it doesn't, we have actually no idea if another // embedding would do. // The better solution would be to incorporate the acyclicity // property into the upward-planarity test, but this is compicated. //**************************************************************** // test if original graph plus augmented edges is still acyclic if(checkAcyclic(graphAcyclicTest,tmpAugmented) == true) { augmented = tmpAugmented; } else { // if not, remove eG from subgraph H.delEdge(eH); delEdges.pushBack(eG); } } } // remove edges not in the subgraph from GC ListConstIterator<edge> itE; for(itE = delEdges.begin(); itE.valid(); ++itE) GC.delEdge(GC.copy(*itE)); // add augmented edges to GC SListConstIterator<Tuple2<node,node> > itP; for(itP = augmented.begin(); itP.valid(); ++itP) { node v = (*itP).x1(); node w = (*itP).x2(); GC.newEdge(GC.copy(v),GC.copy(w)); } // add super sink to GC node sGC = nullptr; SList<node> sinks; for(node v : GC.nodes) { if(v->indeg() == 0) sGC = v; if(v->outdeg() == 0) sinks.pushBack(v); } node superSinkGC = GC.newNode(); SListConstIterator<node> itV; for(itV = sinks.begin(); itV.valid(); ++itV) GC.newEdge(*itV,superSinkGC); // add st-edge to GC, so that we now have a planar st-digraph GC.newEdge(sGC,superSinkGC); OGDF_ASSERT(isAcyclic(GC)); OGDF_ASSERT(isPlanar(GC)); }
void PlanarizationGridLayout::doCall( const Graph &G, GridLayout &gridLayout, IPoint &bb) { m_nCrossings = 0; if(G.empty()) return; PlanRep pr(G); const int numCC = pr.numberOfCCs(); // (width,height) of the layout of each connected component Array<IPoint> boundingBox(numCC); for(int cc = 0; cc < numCC; ++cc) { //-------------------------------------- // 1. crossing minimization //-------------------------------------- int cr; m_crossMin.get().call(pr, cc, cr); m_nCrossings += cr; OGDF_ASSERT(isPlanar(pr)); GridLayout gridLayoutPG(pr); m_planarLayouter.get().callGrid(pr,gridLayoutPG); // copy grid layout of PG into grid layout of G for(int j = pr.startNode(); j < pr.stopNode(); ++j) { node vG = pr.v(j); gridLayout.x(vG) = gridLayoutPG.x(pr.copy(vG)); gridLayout.y(vG) = gridLayoutPG.y(pr.copy(vG)); adjEntry adj; forall_adj(adj,vG) { if ((adj->index() & 1) == 0) continue; edge eG = adj->theEdge(); IPolyline &ipl = gridLayout.bends(eG); ipl.clear(); bool firstTime = true; ListConstIterator<edge> itE; for(itE = pr.chain(eG).begin(); itE.valid(); ++itE) { if(!firstTime) { node v = (*itE)->source(); ipl.pushBack(IPoint(gridLayoutPG.x(v),gridLayoutPG.y(v))); } else firstTime = false; ipl.conc(gridLayoutPG.bends(*itE)); } } } boundingBox[cc] = m_planarLayouter.get().gridBoundingBox(); boundingBox[cc].m_x += 1; // one row/column space between components boundingBox[cc].m_y += 1; } Array<IPoint> offset(numCC); m_packer.get().call(boundingBox,offset,m_pageRatio); bb.m_x = bb.m_y = 0; for(int cc = 0; cc < numCC; ++cc) { const int dx = offset[cc].m_x; const int dy = offset[cc].m_y; if(boundingBox[cc].m_x + dx > bb.m_x) bb.m_x = boundingBox[cc].m_x + dx; if(boundingBox[cc].m_y + dy > bb.m_y) bb.m_y = boundingBox[cc].m_y + dy; // iterate over all nodes in i-th cc for(int j = pr.startNode(cc); j < pr.stopNode(cc); ++j) { node vG = pr.v(j); gridLayout.x(vG) += dx; gridLayout.y(vG) += dy; adjEntry adj; forall_adj(adj,vG) { if ((adj->index() & 1) == 0) continue; edge eG = adj->theEdge(); ListIterator<IPoint> it; for(it = gridLayout.bends(eG).begin(); it.valid(); ++it) { (*it).m_x += dx; (*it).m_y += dy; } } } } bb.m_x -= 1; // remove margin of topmost/rightmost box bb.m_y -= 1; }
/*! Returns the number fo planes for the pixel format \a format */ int QVideoFrame::planesCount( PixelFormat format ) { return isPlanar( format ) ? 3 : 1; }
int AudioFormat::planeCount() const { return isPlanar() ? 1 : channels(); }
void TriconnectedShellingOrder::doCall( const Graph& G, adjEntry adj, List<ShellingOrderSet>& partition) { // prefer nodes to faces? bool preferNodes = false; #ifdef OUTPUT_TSO cout << "Graph G is planar == " << isPlanar(G) << endl; cout << "Graph G has no self loops == " << isLoopFree(G) << endl; cout << "Graph G is connected == " << isConnected(G) << endl; cout << "Graph G is triconnected == " << isTriconnected(G) << endl; #endif OGDF_ASSERT(isPlanar(G) == true); OGDF_ASSERT(isLoopFree(G) == true); OGDF_ASSERT(isTriconnected(G) == true); // crate an embedding for G ConstCombinatorialEmbedding E(G); // set outerFace so adj is on it or to face with maximal size face outerFace = (adj != nullptr) ? E.rightFace(adj) : E.maximalFace(); #ifdef OUTPUT_TSO cout << "faces:" << endl; for(face fh : E.faces) { if (fh == outerFace) cout << " face *" << fh->index() << ":"; else cout << " face " << fh->index() << ":"; for(adjEntry adj : fh->entries) cout << " " << adj; cout << endl; } cout << "adjacency lists:" << endl; for(node vh : G.nodes) { cout << " node " << vh << ":"; for(adjEntry adj : vh->adjEntries) cout << " " << adj; cout << endl; } #endif adjEntry firstAdj = outerFace->firstAdj(); // set firstAdj that the outer face is on the left of firstAdj if (E.rightFace(firstAdj) == outerFace) firstAdj = firstAdj->cyclicSucc(); // set "base" nodes v1, v2 on outer face with edge [v1,v2] node v1 = firstAdj->theNode(); node v2 = firstAdj->cyclicPred()->twinNode(); ComputeTricOrder cto(G, E, outerFace, m_baseRatio, preferNodes); // if outerFace == {v_1,...,v_q} // adjPred(v_i) == v_i -> v_{i-1} // adjSucc(v_i) == v_1 -> v_{i+1} // these arrays will be updated during the algo so they define the outer face NodeArray<adjEntry> adjPred(G), adjSucc(G); // init adjPred and adjSucc for the nodes of the outer face adjSucc[v1] = firstAdj; adjEntry adjRun = firstAdj->twin()->cyclicSucc(); do { adjPred[adjRun->theNode()] = adjRun->cyclicPred(); adjSucc[adjRun->theNode()] = adjRun; adjRun = adjRun->twin()->cyclicSucc(); } while (adjRun != firstAdj); adjPred[v1] = adjSucc[v2] = nullptr; // init outer nodes and outer edges cto.initOuterNodes(v1, v2); cto.initOuterEdges(); // init the first possible node as the node in the middle of v_1 // and v_2 on the outer face int l = (outerFace->size() -2)/2; if (l == 0) l = 1; adjRun = firstAdj; for (int i=1; i <= l; i++) adjRun = adjRun->twin()->cyclicSucc(); cto.initPossible(adjRun->theNode()); // node and face that are selected during the algorithm node vk; face Fk; // left and right node of current nodeset node cl, cr; // the actual nodeset V in the shelling order ShellingOrderSet V; // further auxiliary variables #ifdef OUTPUT_TSO cout << "finished initialization of cto, adjSucc, adjPred." << endl << flush; cout << "v1 = " << v1 << ", v2 = " << v2 << ", first possible node = " << adjRun->theNode() << endl; for(adjEntry adj1 : outerFace->entries) { cout << " node " << adj1->theNode() << ": adjPred=(" << adjPred[adj1->theNode()] << "), adjSucc=" << adjSucc[adj1->theNode()] << endl; } cto.output(); cout << "starting main loop" << endl; #endif // main loop while (cto.isPossible()){ // get the next possible nodeset for the order cto.getNextPossible(vk, Fk); // check if the current selection is a node or a face if (cto.isNode()){ #ifdef OUTPUT_TSO cout << " nextPossible is node " << vk << endl << flush; #endif // current item is a node V = ShellingOrderSet(1, adjPred[vk], adjSucc[vk]); V[1] = vk; cl = (adjPred[vk])->twinNode(); cr = (adjSucc[vk])->twinNode(); // insert actual nodeset to the front of the shelling order partition.pushFront(V); } else{ #ifdef OUTPUT_TSO cout << " nextPossible is face " << Fk->index() << endl << flush; #endif // current item is a face // create set with chain {z_1,...,z_l} V = ShellingOrderSet(cto.getOutv(Fk)-2); // now find node v on Fk with degree 2 cl = cto.getOuterNodeDeg2(Fk, adjPred, adjSucc); // find end of chain cl and cr // traverse to left while degree == 2 while ((cl != v1) && (adjPred[cl] == adjSucc[cl]->cyclicSucc())) cl = (adjPred[cl])->twinNode(); // traverse to the right while degree == 2 // and insert nodes into the ShellingOrderSet cr = adjSucc[cl]->twinNode(); int i = 1; while ((cr != v2) && (adjPred[cr] == adjSucc[cr]->cyclicSucc())){ V[i] = cr; cr = (adjSucc[cr])->twinNode(); i++; } cto.decSepf(cl); cto.decSepf(cr); // set left and right node in the shelling order set V.left(cl); V.right(cr); // set left and right adjacency entry V.leftAdj((adjPred[cr])->twin()); V.rightAdj((adjSucc[cl])->twin()); // insert actual nodeset to the front of the shelling order partition.pushFront(V); }// current item is a face #ifdef OUTPUT_TSO cout << " set cl = " << cl << endl; cout << " set cr = " << cr << endl; #endif // update adjSucc[cl] and adjPred[cr] adjSucc[cl] = adjSucc[cl]->cyclicSucc(); adjPred[cr] = adjPred[cr]->cyclicPred(); // increase number of outer edges of face left of adjPred[cr] cto.incOute(E.leftFace(adjPred[cr])); cto.incVisited(cl); cto.incVisited(cr); // traverse from cl to cr on the new outer face // and update adjSucc[] and adjPred[] adjEntry adj1 = adjSucc[cl]->twin(); for (node u = adj1->theNode(); u != cr; u = adj1->theNode()){ // increase oute for the right face of adj1 cto.incOute(E.leftFace(adj1)); // set new predecessor adjPred[u] = adj1; // go to next adj-entry adj1 = adj1->cyclicSucc(); // if the actual node has an edge to the deleted node // increase the visited value for the actual node... if (adj1->twinNode() == vk){ cto.incVisited(u); // ... and skip the actual adjEntry adj1 = adj1->cyclicSucc(); } adjSucc[u] = adj1; // add actual node to outerNodes[f] for (adjEntry adj2 = adjPred[u]; adj2 != adjSucc[u]; adj2 = adj2->cyclicPred()){ cto.addOuterNode(u, E.leftFace(adj2)); } adj1 = adj1->twin(); } if (!cto.isNode()){ if ( ((adjSucc[cl])->twinNode() == cr) && ( cto.isOnlyEdge(E.rightFace(adjSucc[cl])) ) ){ cto.decSepf(cl); cto.decSepf(cr); } } // update cto cto.doUpdate(); #ifdef OUTPUT_TSO cto.output(); #endif }// while (cto.isPossible()) // finally push the base (v1,v2) to the order V = ShellingOrderSet(2); V[1] = v1; V[2] = v2; partition.pushFront(V); #ifdef OUTPUT_TSO cout << "output of the computed partition:" << endl; int k = 1; for (const ShellingOrderSet &S : partition) { int size = S.len(); cout << "nodeset with nr " << k << ":" << endl; for (int j=1; j<=size; j++) cout << " node " << S[j] <<", "; cout << "." << endl; } #endif }// void TriconnectedShellingOrder::doCall
Module::ReturnType SubgraphPlanarizerUML::doCall( PlanRepUML &pr, int cc, const EdgeArray<int> *pCostOrig, int &crossingNumber) { OGDF_ASSERT(m_permutations >= 1); PlanarSubgraphModule &subgraph = m_subgraph.get(); UMLEdgeInsertionModule &inserter = m_inserter.get(); unsigned int nThreads = min(m_maxThreads, (unsigned int)m_permutations); int64_t startTime; System::usedRealTime(startTime); int64_t stopTime = (m_timeLimit >= 0) ? (startTime + int64_t(1000.0*m_timeLimit)) : -1; // // Compute subgraph // if(m_setTimeout) subgraph.timeLimit(m_timeLimit); pr.initCC(cc); // gather generalization edges, which should all be in the planar subgraph List<edge> preferedEdges; for(edge e : pr.edges) { if (pr.typeOf(e) == Graph::generalization) preferedEdges.pushBack(e); } List<edge> delEdges; ReturnType retValue; if(pCostOrig) { EdgeArray<int> costPG(pr); for(edge e : pr.edges) costPG[e] = (*pCostOrig)[pr.original(e)]; retValue = subgraph.call(pr, costPG, preferedEdges, delEdges); } else retValue = subgraph.call(pr, preferedEdges, delEdges); if(isSolution(retValue) == false) return retValue; const int m = delEdges.size(); for(ListIterator<edge> it = delEdges.begin(); it.valid(); ++it) *it = pr.original(*it); // // Permutation phase // int seed = rand(); minstd_rand rng(seed); if(nThreads > 1) { // // Parallel implementation // ThreadMaster master( pr, cc, pCostOrig, delEdges, seed, m_permutations - nThreads, stopTime); Array<Worker *> worker(nThreads-1); Array<Thread> thread(nThreads-1); for(unsigned int i = 0; i < nThreads-1; ++i) { worker[i] = new Worker(i, &master, inserter.clone()); thread[i] = Thread(*worker[i]); } doWorkHelper(master, inserter, rng); for(unsigned int i = 0; i < nThreads-1; ++i) { thread[i].join(); delete worker[i]; } master.restore(pr, crossingNumber); } else { // // Sequential implementation // PlanRepLight prl(pr); Array<edge> deletedEdges(m); int j = 0; for(ListIterator<edge> it = delEdges.begin(); it.valid(); ++it) deletedEdges[j++] = *it; bool foundSolution = false; CrossingStructure cs; for(int i = 1; i <= m_permutations; ++i) { int cr; bool ok = doSinglePermutation(prl, cc, pCostOrig, deletedEdges, inserter, rng, cr); if(ok && (foundSolution == false || cr < cs.weightedCrossingNumber())) { foundSolution = true; cs.init(prl, cr); } if(stopTime >= 0 && System::realTime() >= stopTime) { if(foundSolution == false) return retTimeoutInfeasible; // not able to find a solution... break; } } cs.restore(pr,cc); // restore best solution in PG crossingNumber = cs.weightedCrossingNumber(); OGDF_ASSERT(isPlanar(pr) == true); } return retFeasible; }