You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
678 lines
24 KiB
678 lines
24 KiB
/****************************************************************************
|
|
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
|
|
|
http://www.cocos.com
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights to
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#pragma once
|
|
#include <boost/graph/adjacency_iterator.hpp>
|
|
#include <boost/graph/properties.hpp>
|
|
#include <boost/iterator/iterator_adaptor.hpp>
|
|
#include <functional>
|
|
#include "cocos/base/std/container/vector.h"
|
|
#include "cocos/base/std/variant.h"
|
|
#include "cocos/renderer/pipeline/custom/details/GraphTypes.h"
|
|
#include "cocos/renderer/pipeline/custom/details/GslUtils.h"
|
|
|
|
namespace cc {
|
|
|
|
namespace render {
|
|
|
|
namespace impl {
|
|
|
|
//--------------------------------------------------------------------
|
|
// PropertyMap
|
|
//--------------------------------------------------------------------
|
|
template <class Category, class Graph, class Value, class Reference>
|
|
struct VectorVertexBundlePropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, VectorVertexBundlePropertyMap<Category, Graph, Value, Reference>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::vertex_descriptor;
|
|
using category = Category;
|
|
|
|
VectorVertexBundlePropertyMap(Graph &g) noexcept // NOLINT(google-explicit-constructor)
|
|
: graph(&g) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
return graph->mVertices[v].property;
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Graph *graph{};
|
|
};
|
|
|
|
template <class Category, class Graph, class Value, class Reference>
|
|
struct PointerVertexBundlePropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, PointerVertexBundlePropertyMap<Category, Graph, Value, Reference>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::vertex_descriptor;
|
|
using category = Category;
|
|
|
|
PointerVertexBundlePropertyMap(Graph &g) noexcept // NOLINT(google-explicit-constructor)
|
|
: graph(&g) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
auto *sv = static_cast<typename Graph::vertex_type *>(v);
|
|
return sv->property;
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Graph *graph{};
|
|
};
|
|
|
|
template <class Category, class Graph, class Value, class Reference, class MemberPointer>
|
|
struct VectorVertexBundleMemberPropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, VectorVertexBundleMemberPropertyMap<Category, Graph, Value, Reference, MemberPointer>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::vertex_descriptor;
|
|
using category = Category;
|
|
|
|
VectorVertexBundleMemberPropertyMap(Graph &g, MemberPointer ptr) noexcept
|
|
: graph(&g), memberPointer(ptr) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
return graph->mVertices[v].property.*memberPointer;
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Graph *graph{};
|
|
MemberPointer memberPointer{};
|
|
};
|
|
|
|
template <class Category, class Graph, class Value, class Reference, class MemberPointer>
|
|
struct PointerVertexBundleMemberPropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, PointerVertexBundleMemberPropertyMap<Category, Graph, Value, Reference, MemberPointer>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::vertex_descriptor;
|
|
using category = Category;
|
|
|
|
PointerVertexBundleMemberPropertyMap(Graph &g, MemberPointer ptr) noexcept
|
|
: graph(&g), memberPointer(ptr) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
auto *sv = static_cast<typename Graph::vertex_type *>(v);
|
|
return sv->property.*memberPointer;
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Graph *graph{};
|
|
MemberPointer memberPointer{};
|
|
};
|
|
|
|
template <class Category, class Graph, class Container, class Value, class Reference>
|
|
struct VectorVertexComponentPropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, VectorVertexComponentPropertyMap<Category, Graph, Container, Value, Reference>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::vertex_descriptor;
|
|
using category = Category;
|
|
|
|
VectorVertexComponentPropertyMap(Container &c) noexcept // NOLINT(google-explicit-constructor)
|
|
: container(&c) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
return (*container)[v];
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Container *container{};
|
|
};
|
|
|
|
template <class Category, class Graph, class Container, class Value, class Reference, class MemberPointer>
|
|
struct VectorVertexComponentMemberPropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, VectorVertexComponentMemberPropertyMap<Category, Graph, Container, Value, Reference, MemberPointer>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::vertex_descriptor;
|
|
using category = Category;
|
|
|
|
VectorVertexComponentMemberPropertyMap(Container &c, MemberPointer ptr) noexcept
|
|
: container(&c), memberPointer(ptr) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
return (*container)[v].*memberPointer;
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Container *container{};
|
|
MemberPointer memberPointer{};
|
|
};
|
|
|
|
template <class Category, class Graph, class ComponentPointer, class Value, class Reference>
|
|
struct VectorVertexIteratorComponentPropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, VectorVertexIteratorComponentPropertyMap<Category, Graph, ComponentPointer, Value, Reference>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::vertex_descriptor;
|
|
using category = Category;
|
|
|
|
VectorVertexIteratorComponentPropertyMap(Graph &g, ComponentPointer component) noexcept
|
|
: graph(&g), componentPointer(component) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
return *(graph->mVertices[v].*componentPointer);
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Graph *graph{};
|
|
ComponentPointer componentPointer{};
|
|
};
|
|
|
|
template <class Category, class Graph, class ComponentPointer, class Value, class Reference, class MemberPointer>
|
|
struct VectorVertexIteratorComponentMemberPropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, VectorVertexIteratorComponentMemberPropertyMap<Category, Graph, ComponentPointer, Value, Reference, MemberPointer>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::vertex_descriptor;
|
|
using category = Category;
|
|
|
|
VectorVertexIteratorComponentMemberPropertyMap(Graph &g, ComponentPointer component, MemberPointer ptr) noexcept
|
|
: graph(&g), componentPointer(component), memberPointer(ptr) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
return (*(graph->mVertices[v].*componentPointer)).*memberPointer;
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Graph *graph{};
|
|
ComponentPointer componentPointer{};
|
|
MemberPointer memberPointer{};
|
|
};
|
|
|
|
template <class Category, class VertexDescriptor, class Container, class Value, class Reference>
|
|
struct VectorPathPropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, VectorPathPropertyMap<Category, VertexDescriptor, Container, Value, Reference>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = VertexDescriptor;
|
|
using category = Category;
|
|
|
|
VectorPathPropertyMap(Container &c) noexcept // NOLINT(google-explicit-constructor)
|
|
: container(&c) {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
return (*container)[v].mPathIterator->first;
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
Container *container{};
|
|
};
|
|
|
|
template <class Category, class Graph, class Value, class Reference>
|
|
struct EdgeBundlePropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, EdgeBundlePropertyMap<Category, Graph, Value, Reference>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::edge_descriptor;
|
|
using category = Category;
|
|
|
|
EdgeBundlePropertyMap(Graph &g) noexcept // NOLINT(google-explicit-constructor)
|
|
: graph(&g) {}
|
|
|
|
inline reference operator[](const key_type &e) const noexcept {
|
|
return *static_cast<typename Graph::edge_property_type *>(e.get_property());
|
|
}
|
|
inline reference operator()(const key_type &e) const noexcept {
|
|
return operator[](e);
|
|
}
|
|
|
|
Graph *graph{};
|
|
};
|
|
|
|
template <class Category, class Graph, class Value, class Reference, class MemberPointer>
|
|
struct EdgeBundleMemberPropertyMap
|
|
: public boost::put_get_helper<
|
|
Reference, EdgeBundleMemberPropertyMap<Category, Graph, Value, Reference, MemberPointer>> {
|
|
using value_type = Value;
|
|
using reference = Reference;
|
|
using key_type = typename Graph::edge_descriptor;
|
|
using category = Category;
|
|
|
|
EdgeBundleMemberPropertyMap(Graph &g, MemberPointer ptr) noexcept
|
|
: graph(&g), memberPointer(ptr) {}
|
|
|
|
inline reference operator[](const key_type &e) const noexcept {
|
|
auto &p = *static_cast<typename Graph::edge_property_type *>(e.get_property());
|
|
return p.*memberPointer;
|
|
}
|
|
inline reference operator()(const key_type &e) const noexcept {
|
|
return operator[](e);
|
|
}
|
|
|
|
Graph *graph{};
|
|
MemberPointer memberPointer{};
|
|
};
|
|
|
|
template <class Sequence, class Predicate>
|
|
void sequenceEraseIf(Sequence &c, Predicate &&p) noexcept {
|
|
if (!c.empty()) {
|
|
c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
|
|
}
|
|
}
|
|
|
|
// notice: Predicate might be different from associative key
|
|
// when Predicate is associative key, it is slower than erase [lower_bound, upper_bound)
|
|
template <class AssociativeContainer, class Predicate>
|
|
void associativeEraseIf(AssociativeContainer &c, Predicate &&p) noexcept {
|
|
auto next = c.begin();
|
|
for (auto i = next; next != c.end(); i = next) {
|
|
++next;
|
|
if (p(*i)) {
|
|
c.erase(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
// notice: Predicate might be different from associative key
|
|
// when Predicate is associative key, it is slower than erase [lower_bound, upper_bound)
|
|
template <class AssociativeContainer, class Predicate>
|
|
void unstableAssociativeEraseIf(AssociativeContainer &c, Predicate &&p) noexcept {
|
|
auto n = c.size();
|
|
while (n--) {
|
|
for (auto i = c.begin(); i != c.end(); ++i) {
|
|
if (p(*i)) {
|
|
c.erase(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class EdgeDescriptor, class IncidenceList>
|
|
inline void removeIncidenceEdge(EdgeDescriptor e, IncidenceList &el) noexcept {
|
|
e.expectsNoProperty();
|
|
for (auto i = el.begin(); i != el.end(); ++i) {
|
|
if ((*i).get_target() == e.target) {
|
|
el.erase(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class DirectedCategory, class VertexDescriptor, class IncidenceList, class EdgeProperty>
|
|
inline void removeIncidenceEdge(
|
|
EdgeDescriptorWithProperty<DirectedCategory, VertexDescriptor> e, IncidenceList &el) noexcept {
|
|
for (auto i = el.begin(); i != el.end(); ++i) {
|
|
if (static_cast<void *>(&(*i).get_property()) == e.get_property()) {
|
|
el.erase(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Graph, class IncidenceList, class VertexDescriptor>
|
|
inline void removeDirectedAllEdgeProperties(Graph &g, IncidenceList &el, VertexDescriptor v) noexcept {
|
|
auto i = el.begin();
|
|
auto end = el.end();
|
|
for (; i != end; ++i) {
|
|
if ((*i).get_target() == v) {
|
|
// NOTE: Wihtout this skip, this loop will double-delete
|
|
// properties of loop edges. This solution is based on the
|
|
// observation that the incidence edges of a vertex with a loop
|
|
// are adjacent in the out edge list. This *may* actually hold
|
|
// for multisets also.
|
|
bool skip = (std::next(i) != end && i->get_iter() == std::next(i)->get_iter());
|
|
g.edges.erase((*i).get_iter());
|
|
if (skip) {
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class IncidenceIterator, class IncidenceList, class Predicate>
|
|
inline void sequenceRemoveIncidenceEdgeIf(IncidenceIterator first, IncidenceIterator last,
|
|
IncidenceList &el, Predicate &&pred) noexcept {
|
|
// remove_if
|
|
while (first != last && !pred(*first)) {
|
|
++first;
|
|
}
|
|
auto i = first;
|
|
if (first != last) {
|
|
for (++i; i != last; ++i) {
|
|
if (!pred(*i)) {
|
|
*first.base() = std::move(*i.base());
|
|
++first;
|
|
}
|
|
}
|
|
}
|
|
el.erase(first.base(), el.end());
|
|
}
|
|
|
|
template <class IncidenceIterator, class IncidenceList, class Predicate>
|
|
inline void associativeRemoveIncidenceEdgeIf(IncidenceIterator first, IncidenceIterator last,
|
|
IncidenceList &el, Predicate &&pred) noexcept {
|
|
for (auto next = first; first != last; first = next) {
|
|
++next;
|
|
if (pred(*first)) {
|
|
el.erase(first.base());
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Graph, class EdgeDescriptor, class EdgeProperty>
|
|
inline void removeUndirectedEdge(Graph &g, EdgeDescriptor e, EdgeProperty &p) noexcept {
|
|
auto &outEdgeList = g.getOutEdgeList(source(e, g));
|
|
auto outEdgeIter = outEdgeList.begin();
|
|
decltype((*outEdgeIter).get_iter()) edgeIterToErase;
|
|
for (; outEdgeIter != outEdgeList.end(); ++outEdgeIter) {
|
|
if (&(*outEdgeIter).get_property() == &p) {
|
|
edgeIterToErase = (*outEdgeIter).get_iter();
|
|
outEdgeList.erase(outEdgeIter);
|
|
break;
|
|
}
|
|
}
|
|
auto &inEdgeList = g.getOutEdgeList(target(e, g));
|
|
auto inEdgeIter = inEdgeList.begin();
|
|
for (; inEdgeIter != inEdgeList.end(); ++inEdgeIter) {
|
|
if (&(*inEdgeIter).get_property() == &p) {
|
|
inEdgeList.erase(inEdgeIter);
|
|
break;
|
|
}
|
|
}
|
|
g.edges.erase(edgeIterToErase);
|
|
}
|
|
|
|
template <class Graph, class IncidenceIterator, class IncidenceList, class Predicate>
|
|
inline void sequenceRemoveUndirectedOutEdgeIf(Graph &g,
|
|
IncidenceIterator first, IncidenceIterator last, IncidenceList &el,
|
|
Predicate &&pred) noexcept {
|
|
// remove_if
|
|
while (first != last && !pred(*first)) {
|
|
++first;
|
|
}
|
|
auto i = first;
|
|
bool selfLoopRemoved = false;
|
|
if (first != last) {
|
|
for (; i != last; ++i) {
|
|
if (selfLoopRemoved) {
|
|
/* With self loops, the descriptor will show up
|
|
* twice. The first time it will be removed, and now it
|
|
* will be skipped.
|
|
*/
|
|
selfLoopRemoved = false;
|
|
} else if (!pred(*i)) {
|
|
*first.base() = std::move(*i.base());
|
|
++first;
|
|
} else {
|
|
if (source(*i, g) == target(*i, g)) {
|
|
selfLoopRemoved = true;
|
|
} else {
|
|
// Remove the edge from the target
|
|
removeIncidenceEdge(*i, g.getOutEdgeList(target(*i, g)));
|
|
}
|
|
|
|
// Erase the edge property
|
|
g.edges.erase((*i.base()).get_iter());
|
|
}
|
|
}
|
|
}
|
|
el.erase(first.base(), el.end());
|
|
}
|
|
|
|
template <class Graph, class IncidenceIterator, class IncidenceList, class Predicate>
|
|
inline void associativeRemoveUndirectedOutEdgeIf(Graph &g,
|
|
IncidenceIterator first, IncidenceIterator last, IncidenceList &el,
|
|
Predicate &&pred) noexcept {
|
|
for (auto next = first; first != last; first = next) {
|
|
++next;
|
|
if (pred(*first)) {
|
|
if (source(*first, g) != target(*first, g)) {
|
|
// Remove the edge from the target
|
|
removeIncidenceEdge(*first, g.getOutEdgeList(target(*first, g)));
|
|
}
|
|
|
|
// Erase the edge property
|
|
g.edges.erase((*first.base()).get_iter());
|
|
|
|
// Erase the edge in the source
|
|
el.erase(first.base());
|
|
}
|
|
}
|
|
}
|
|
|
|
// list/vector out_edge_list
|
|
template <class IncidenceList, class VertexDescriptor>
|
|
inline void reindexEdgeList(IncidenceList &el, VertexDescriptor u) {
|
|
auto ei = el.begin();
|
|
auto eEnd = el.end();
|
|
for (; ei != eEnd; ++ei) {
|
|
if ((*ei).get_target() > u) {
|
|
--(*ei).get_target();
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Tag, class Container, class HandleDescriptor>
|
|
inline void reindexVectorHandle(Container &container, HandleDescriptor u) {
|
|
static_assert(std::is_arithmetic<HandleDescriptor>::value, "reindexVectorHandle");
|
|
|
|
using handle_type = ValueHandle<Tag, HandleDescriptor>;
|
|
for (auto &vert : container) {
|
|
if (ccstd::holds_alternative<handle_type>(vert.handle)) {
|
|
auto &v = ccstd::get<handle_type>(vert.handle).value;
|
|
if (v > u) {
|
|
--v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Graph, class VertexDescriptor>
|
|
inline void removeVectorVertex(Graph &g, VertexDescriptor u, boost::directed_tag /*tag*/) {
|
|
g._vertices.erase(g._vertices.begin() + u);
|
|
auto numV = num_vertices(g);
|
|
if (u != numV) {
|
|
for (VertexDescriptor v = 0; v < numV; ++v) {
|
|
reindexEdgeList(g.getOutEdgeList(v), u);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Graph, class VertexDescriptor>
|
|
inline void removeVectorVertex(Graph &g, VertexDescriptor u, boost::undirected_tag /*tag*/) {
|
|
g._vertices.erase(g._vertices.begin() + u);
|
|
VertexDescriptor numV = num_vertices(g);
|
|
for (VertexDescriptor v = 0; v < numV; ++v) {
|
|
reindexEdgeList(g.getOutEdgeList(v), u);
|
|
}
|
|
|
|
auto ei = g.edges.begin();
|
|
auto eiEnd = g.edges.end();
|
|
for (; ei != eiEnd; ++ei) {
|
|
if (ei->source > u) {
|
|
--ei->source;
|
|
}
|
|
if (ei->target > u) {
|
|
--ei->target;
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Graph, class VertexDescriptor>
|
|
inline void removeVectorVertex(Graph &g, VertexDescriptor u, boost::bidirectional_tag /*tag*/) {
|
|
g._vertices.erase(g._vertices.begin() + u);
|
|
VertexDescriptor numV = num_vertices(g);
|
|
VertexDescriptor v;
|
|
if (u != numV) {
|
|
for (v = 0; v < numV; ++v) {
|
|
reindexEdgeList(g.getOutEdgeList(v), u);
|
|
}
|
|
|
|
for (v = 0; v < numV; ++v) {
|
|
reindexEdgeList(g.getInEdgeList(v), u);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Graph, class VertexDescriptor, class EdgeList>
|
|
inline void removeVectorVertex(Graph &g, EdgeList & /*edges*/,
|
|
VertexDescriptor u, boost::bidirectional_tag /*tag*/) {
|
|
g._vertices.erase(g._vertices.begin() + u);
|
|
VertexDescriptor numV = num_vertices(g);
|
|
VertexDescriptor v;
|
|
if (u != numV) {
|
|
for (v = 0; v < numV; ++v) {
|
|
reindexEdgeList(g.getOutEdgeList(v), u);
|
|
}
|
|
|
|
for (v = 0; v < numV; ++v) {
|
|
reindexEdgeList(g.getInEdgeList(v), u);
|
|
}
|
|
|
|
auto ei = g.edges.begin();
|
|
auto eiEnd = g.edges.end();
|
|
for (; ei != eiEnd; ++ei) {
|
|
if (ei->source > u) {
|
|
--ei->source;
|
|
}
|
|
if (ei->target > u) {
|
|
--ei->target;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Graph>
|
|
inline void removeVectorOwner(Graph &g, typename Graph::vertex_descriptor u) {
|
|
// might make children detached
|
|
g.mObjects.erase(g.mObjects.begin() + u);
|
|
auto numV = num_vertices(g);
|
|
if (u != numV) {
|
|
for (typename Graph::vertex_descriptor v = 0; v < numV; ++v) {
|
|
reindexEdgeList(g.getChildrenList(v), u);
|
|
}
|
|
|
|
for (typename Graph::vertex_descriptor v = 0; v < numV; ++v) {
|
|
reindexEdgeList(g.getParentsList(v), u);
|
|
}
|
|
}
|
|
}
|
|
|
|
// AddressableGraph
|
|
template <class AddressableGraph>
|
|
inline std::ptrdiff_t pathLength(typename AddressableGraph::vertex_descriptor u, const AddressableGraph &g,
|
|
typename AddressableGraph::vertex_descriptor parentID = AddressableGraph::null_vertex()) noexcept {
|
|
if (u == parentID) {
|
|
return 0;
|
|
}
|
|
|
|
const auto &pmap = get(boost::vertex_name, g);
|
|
|
|
std::ptrdiff_t sz = 0;
|
|
while (u != parentID) {
|
|
sz += static_cast<std::ptrdiff_t>(get(pmap, u).size()) + 1;
|
|
u = parent(u, g);
|
|
}
|
|
|
|
return sz;
|
|
}
|
|
|
|
template <class AddressableGraph, class CharT, class Allocator>
|
|
inline void pathComposite(
|
|
std::basic_string<CharT, std::char_traits<CharT>, Allocator> &str,
|
|
std::ptrdiff_t &sz,
|
|
typename AddressableGraph::vertex_descriptor u, const AddressableGraph &g,
|
|
typename AddressableGraph::vertex_descriptor parentID = AddressableGraph::null_vertex()) noexcept {
|
|
const auto &pmap = get(boost::vertex_name, g);
|
|
|
|
while (u != parentID) {
|
|
CC_EXPECTS(sz <= static_cast<std::ptrdiff_t>(str.size()));
|
|
|
|
const auto &name = get(pmap, u);
|
|
sz -= static_cast<std::ptrdiff_t>(name.size()) + 1;
|
|
CC_ENSURES(sz >= 0);
|
|
str[sz] = '/';
|
|
std::copy(name.begin(), name.end(), str.begin() + sz + 1);
|
|
|
|
u = parent(u, g);
|
|
}
|
|
CC_ENSURES(sz == 0);
|
|
}
|
|
|
|
template <class Key>
|
|
struct ColorMap : public boost::put_get_helper<boost::default_color_type &, ColorMap<Key>> {
|
|
using value_type = boost::default_color_type;
|
|
using reference = boost::default_color_type &;
|
|
using key_type = Key;
|
|
using category = boost::lvalue_property_map_tag;
|
|
|
|
ColorMap(ccstd::pmr::vector<boost::default_color_type> &vec) noexcept // NOLINT(google-explicit-constructor)
|
|
: container{&vec} {}
|
|
|
|
inline reference operator[](const key_type &v) const noexcept {
|
|
return (*container)[v];
|
|
}
|
|
inline reference operator()(const key_type &v) const noexcept {
|
|
return operator[](v);
|
|
}
|
|
|
|
ccstd::pmr::vector<boost::default_color_type> *container{};
|
|
};
|
|
|
|
} // namespace impl
|
|
|
|
} // namespace render
|
|
|
|
} // namespace cc
|
|
|
|
namespace std {
|
|
|
|
template <class DirectedCategory, class VertexDescriptor>
|
|
struct hash<cc::render::impl::EdgeDescriptor<DirectedCategory, VertexDescriptor>> {
|
|
size_t operator()(const cc::render::impl::EdgeDescriptor<DirectedCategory, VertexDescriptor> &e) const noexcept {
|
|
return boost::hash_value(e.get_property());
|
|
}
|
|
};
|
|
|
|
} // namespace std
|
|
|