37 template <
typename Real>
51 std::vector<std::array<Real, 2>>
const& positions,
52 std::vector<std::array<int, 2>>
const& edges,
53 std::vector<std::shared_ptr<Tree>>& forest);
62 Vertex(
int inName, std::array<Real, 2>
const* inPosition);
63 bool operator< (
Vertex const& vertex)
const;
91 std::shared_ptr<Tree>
ExtractBasis(std::vector<Vertex*>& component);
95 std::vector<int>
ExtractCycle(std::vector<Vertex*>& closedWalk);
106 template <
typename Real>
108 std::vector<std::array<int, 2>>
const& edges, std::vector<std::shared_ptr<Tree>>& forest)
111 if (positions.size() == 0 || edges.size() == 0)
118 std::map<int, std::shared_ptr<Vertex>> unique;
119 for (
auto const& edge : edges)
121 for (
int i = 0; i < 2; ++i)
124 if (unique.find(name) == unique.end())
126 std::shared_ptr<Vertex> vertex =
127 std::make_shared<Vertex>(
name, &positions[
name]);
128 unique.insert(std::make_pair(name, vertex));
135 std::vector<Vertex*> vertices;
137 vertices.reserve(unique.size());
138 for (
auto const& element : unique)
141 vertices.push_back(element.second.get());
145 for (
auto const& edge : edges)
147 auto iter0 = unique.find(edge[0]);
148 auto iter1 = unique.find(edge[1]);
149 iter0->second->adjacent.insert(iter1->second.get());
150 iter1->second->adjacent.insert(iter0->second.get());
159 if (vInitial->visited == 0)
161 components.push_back(std::vector<Vertex*>());
169 for (
auto vertex : mVertexStorage)
175 for (
auto& component : components)
181 template <
typename Real>
184 std::stack<Vertex*> vStack;
185 vStack.push(vInitial);
186 while (vStack.size() > 0)
188 Vertex* vertex = vStack.top();
191 for (
auto adjacent : vertex->
adjacent)
193 if (adjacent && adjacent->visited == 0)
195 vStack.push(adjacent);
204 component.push_back(vertex);
210 template <
typename Real>
211 std::shared_ptr<typename MinimalCycleBasis<Real>::Tree>
216 std::shared_ptr<Tree> tree = std::make_shared<Tree>();
217 while (component.size() > 0)
220 if (component.size() > 0)
226 if (tree->cycle.size() == 0 && tree->children.size() == 1)
230 std::shared_ptr<Tree> child = tree->children.back();
231 tree->cycle = std::move(child->cycle);
232 tree->children = std::move(child->children);
237 template <
typename Real>
242 std::vector<Vertex*> endpoints;
243 for (
auto vertex : component)
245 if (vertex->adjacent.size() == 1)
247 endpoints.push_back(vertex);
251 if (endpoints.size() > 0)
257 for (
auto vertex : endpoints)
259 if (vertex->adjacent.size() == 1)
262 while (vertex->adjacent.size() == 1)
267 vertex->adjacent.erase(adjacent);
278 std::vector<Vertex*> remaining;
279 remaining.reserve(component.size());
280 for (
auto vertex : component)
282 if (vertex->adjacent.size() > 0)
284 remaining.push_back(vertex);
287 component = std::move(remaining);
291 template <
typename Real>
292 std::shared_ptr<typename MinimalCycleBasis<Real>::Tree>
298 Vertex* minVertex = component[0];
299 for (
auto vertex : component)
301 if (*vertex->position < *minVertex->
position)
309 std::vector<Vertex*> closedWalk;
310 Vertex* vCurr = minVertex;
312 closedWalk.push_back(vStart);
314 while (vAdj != vStart)
316 closedWalk.push_back(vAdj);
321 closedWalk.push_back(vStart);
328 std::vector<Vertex*> remaining;
329 remaining.reserve(component.size());
330 for (
auto vertex : component)
332 if (vertex->adjacent.size() > 0)
334 remaining.push_back(vertex);
337 component = std::move(remaining);
342 template <
typename Real>
343 std::shared_ptr<typename MinimalCycleBasis<Real>::Tree>
346 std::shared_ptr<Tree> tree = std::make_shared<Tree>();
348 std::map<Vertex*, int> duplicates;
349 std::set<int> detachments;
350 int numClosedWalk =
static_cast<int>(closedWalk.size());
351 for (
int i = 1; i < numClosedWalk - 1; ++i)
353 auto diter = duplicates.find(closedWalk[i]);
354 if (diter == duplicates.end())
357 duplicates.insert(std::make_pair(closedWalk[i], i));
364 int iMin = diter->second, iMax = i;
365 detachments.insert(iMin);
366 for (
int j = iMin + 1; j < iMax; ++j)
368 Vertex* vertex = closedWalk[j];
369 duplicates.erase(vertex);
370 detachments.erase(j);
372 closedWalk.erase(closedWalk.begin() + iMin + 1, closedWalk.begin() + iMax + 1);
373 numClosedWalk =
static_cast<int>(closedWalk.size());
377 if (numClosedWalk > 3)
387 detachments.insert(0);
390 for (
auto i : detachments)
392 Vertex* original = closedWalk[i];
393 Vertex* maxVertex = closedWalk[i + 1];
394 Vertex* minVertex = (i > 0 ? closedWalk[i - 1] : closedWalk[numClosedWalk - 2]);
396 std::array<Real, 2> dMin, dMax;
397 for (
int j = 0; j < 2; ++j)
403 bool isConvex = (dMax[0] * dMin[1] >= dMax[1] * dMin[0]); (
void)isConvex;
405 std::set<Vertex*> inWedge;
406 std::set<Vertex*> adjacent = original->
adjacent;
407 for (
auto vertex : adjacent)
409 if (vertex->name == minVertex->
name || vertex->name == maxVertex->
name)
414 std::array<Real, 2> dVer;
415 for (
int j = 0; j < 2; ++j)
417 dVer[j] = (*vertex->position)[j] - (*original->
position)[j];
424 dVer[0] * dMin[1] > dVer[1] * dMin[0] &&
425 dVer[0] * dMax[1] < dVer[1] * dMax[0];
430 (dVer[0] * dMin[1] > dVer[1] * dMin[0]) ||
431 (dVer[0] * dMax[1] < dVer[1] * dMax[0]);
435 inWedge.insert(vertex);
439 if (inWedge.size() > 0)
445 std::shared_ptr<Vertex> clone =
446 std::make_shared<Vertex>(original->
name, original->
position);
450 for (
auto vertex : inWedge)
453 vertex->adjacent.erase(original);
454 clone->adjacent.insert(vertex);
455 vertex->adjacent.insert(clone.get());
459 std::vector<Vertex*> component;
475 Vertex* original = closedWalk[0];
476 Vertex* adjacent = closedWalk[1];
478 std::shared_ptr<Vertex> clone =
479 std::make_shared<Vertex>(original->
name, original->
position);
484 clone->adjacent.insert(adjacent);
485 adjacent->
adjacent.insert(clone.get());
488 std::vector<Vertex*> component;
493 if (tree->cycle.size() == 0 && tree->children.size() == 1)
497 std::shared_ptr<Tree> child = tree->children.back();
498 tree->cycle = std::move(child->cycle);
499 tree->children = std::move(child->children);
506 template <
typename Real>
513 int const numVertices =
static_cast<int>(closedWalk.size());
514 std::vector<int>
cycle(numVertices);
515 for (
int i = 0; i < numVertices; ++i)
517 cycle[i] = closedWalk[i]->name;
528 while (v1 != vBranch && v1->
adjacent.size() == 1)
547 while (v0 != vBranch && v0->
adjacent.size() == 1)
560 template <
typename Real>
565 bool vCurrConvex =
false;
566 std::array<Real, 2> dCurr, dNext;
574 dCurr[0] =
static_cast<Real
>(0);
575 dCurr[1] =
static_cast<Real
>(-1);
587 std::array<Real, 2> dAdj;
588 dAdj[0] = (*vAdj->position)[0] - (*vCurr->
position)[0];
589 dAdj[1] = (*vAdj->position)[1] - (*vCurr->
position)[1];
596 vCurrConvex = (dNext[0] * dCurr[1] <= dNext[1] * dCurr[0]);
604 if (dCurr[0] * dAdj[1] < dCurr[1] * dAdj[0]
605 || dNext[0] * dAdj[1] < dNext[1] * dAdj[0])
609 vCurrConvex = (dNext[0] * dCurr[1] <= dNext[1] * dCurr[0]);
614 if (dCurr[0] * dAdj[1] < dCurr[1] * dAdj[0]
615 && dNext[0] * dAdj[1] < dNext[1] * dAdj[0])
619 vCurrConvex = (dNext[0] * dCurr[1] < dNext[1] * dCurr[0]);
627 template <
typename Real>
632 bool vCurrConvex =
false;
633 std::array<Real, 2> dCurr, dNext;
641 dCurr[0] =
static_cast<Real
>(0);
642 dCurr[1] =
static_cast<Real
>(-1);
654 std::array<Real, 2> dAdj;
655 dAdj[0] = (*vAdj->position)[0] - (*vCurr->
position)[0];
656 dAdj[1] = (*vAdj->position)[1] - (*vCurr->
position)[1];
663 vCurrConvex = (dNext[0] * dCurr[1] <= dNext[1] * dCurr[0]);
671 if (dCurr[0] * dAdj[1] > dCurr[1] * dAdj[0]
672 && dNext[0] * dAdj[1] > dNext[1] * dAdj[0])
676 vCurrConvex = (dNext[0] * dCurr[1] <= dNext[1] * dCurr[0]);
681 if (dCurr[0] * dAdj[1] > dCurr[1] * dAdj[0]
682 || dNext[0] * dAdj[1] > dNext[1] * dAdj[0])
686 vCurrConvex = (dNext[0] * dCurr[1] <= dNext[1] * dCurr[0]);
694 template <
typename Real>
698 position(inPosition),
703 template <
typename Real>
Vertex(int inName, std::array< Real, 2 > const *inPosition)
std::shared_ptr< Tree > ExtractBasis(std::vector< Vertex * > &component)
MinimalCycleBasis & operator=(MinimalCycleBasis const &)=delete
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
std::vector< int > ExtractCycle(std::vector< Vertex * > &closedWalk)
bool operator<(Vertex const &vertex) const
GLuint const GLchar * name
std::vector< std::shared_ptr< Vertex > > mVertexStorage
static void DepthFirstSearch(Vertex *vInitial, std::vector< Vertex * > &component)
std::shared_ptr< Tree > ExtractCycleFromClosedWalk(std::vector< Vertex * > &closedWalk)
void RemoveFilaments(std::vector< Vertex * > &component)
Vertex * GetClockwiseMost(Vertex *vPrev, Vertex *vCurr) const
GLenum GLenum GLuint components
MinimalCycleBasis(std::vector< std::array< Real, 2 >> const &positions, std::vector< std::array< int, 2 >> const &edges, std::vector< std::shared_ptr< Tree >> &forest)
Vertex * GetCounterclockwiseMost(Vertex *vPrev, Vertex *vCurr) const
std::set< Vertex * > adjacent
std::shared_ptr< Tree > ExtractCycleFromComponent(std::vector< Vertex * > &component)
std::vector< std::shared_ptr< Tree > > children
std::array< Real, 2 > const * position