diff --git a/algoim/organizer/blobtree.hpp b/algoim/organizer/blobtree.hpp index 7c89882..daab9a0 100644 --- a/algoim/organizer/blobtree.hpp +++ b/algoim/organizer/blobtree.hpp @@ -1,16 +1,19 @@ #pragma once #include +#include +#include namespace algoim::organizer { // bitfield struct Blob { - unsigned int isPrimitive : 1; // 1 for leaf - unsigned int nodeOp : 5; // 0 for intersection, 1 for union, 2 for difference + unsigned int isPrimitive : 1; // 1 for leaf + unsigned int nodeOp : 2; // 0 for union, 1 for intersection, 2 for difference // unsigned int ignoreMod : 2; // 目前用不到 - unsigned int inOut : 2; // 0 for unknown, 1 for in, 2 for out - unsigned int isLeft : 1; - unsigned int ancestor : 23; + unsigned int inOut : 2; // 0 for unknown, 1 for in, 2 for out + unsigned int oneChildInOut : 2; // 0 for unknown, 1 for in, 2 for out + unsigned int isLeft : 1; + unsigned int ancestor : 24; }; bool isPrimitive(Blob b) { return b.isPrimitive == 1; } @@ -19,36 +22,78 @@ unsigned int type(Blob b) { return 0; } bool isLeft(Blob b) { return b.isLeft == 1; } -struct BlobTree { - std::vector structure; +class BlobTree +{ +public: + std::vector structure; + std::vector primtiveNodeIdx; + + BlobTree() {} }; -void propagate(BlobTree &tree, unsigned int nodeIdx, bool in) +void propagate(BlobTree& tree, unsigned int nodeIdx, bool in) { const std::size_t rootIdx = tree.structure.size() - 1; + auto& node = tree.structure[nodeIdx]; + assert(node.inOut == 0); + node.inOut = in ? 1 : 2; for (unsigned int nowIdx = nodeIdx; nowIdx != rootIdx; ++nodeIdx) { - unsigned int nextIdx = isLeft(tree.structure[nowIdx]) ? tree.structure[nowIdx].ancestor : nodeIdx + 1; - if (tree.structure[nowIdx].inOut == 2) { + const auto& nowNode = tree.structure[nowIdx]; + unsigned int nextIdx = isLeft(nowNode) ? nowNode.ancestor : nodeIdx + 1; + auto& nextNode = tree.structure[nextIdx]; + if (nextNode.inOut != 0) { return; } + if (nowNode.inOut == 2) { // out - if (tree.structure[nextIdx].nodeOp == 0) { + if (nextNode.nodeOp == 1) { // intersection - tree.structure[nextIdx].inOut = 2; - nextIdx = nowIdx; - continue; - } else if (tree.structure[nextIdx].nodeOp == 2 && isLeft(tree.structure[nowIdx])) { - // difference - tree.structure[nextIdx].inOut = 2; - nextIdx = nowIdx; - // continue; + } else if (nextNode.nodeOp == 2 && isLeft(nowNode)) { + // difference and left + nextNode.inOut = 2; + } else if (nextNode.oneChildInOut == 1) { + // 两种情况,Union: in, Difference: NowNode一定是right,in-out,还是in + nextNode.inOut = 1; + } else if (nextNode.oneChildInOut == 2) { + // 两种情况,Union: out, Difference: out-out, 还是out + nextNode.inOut = 2; } else { + nextNode.oneChildInOut = 2; return; } - } else if (tree.structure[nowIdx].inOut == 1) { + } else if (nowNode.inOut == 1) { // in - // TODO: + if (nextNode.nodeOp == 0) { + // union + nextNode.inOut = 1; + } else if (nextNode.nodeOp == 2 && !isLeft(nowNode)) { + // difference and right + nextNode.inOut = 2; + } else if (nextNode.oneChildInOut == 1) { + // 两种情况,Intersection: in, Difference: in-in,out + nextNode.inOut = nextNode.nodeOp == 1 ? 1 : 2; + } else if (nextNode.oneChildInOut == 2) { + // 两种情况,Intersection: out, Difference: NowNode一定是left,in-out,in + nextNode.inOut = nextNode.nodeOp == 1 ? 2 : 1; + } else { + nextNode.oneChildInOut = 1; + return; + } } + nextIdx = nowIdx; } return; } +// 这里传入的是拷贝,因为要修改,但不同traversal的修改不相互影响 +// TODO: 最好优化掉拷贝 +// TODO: std::vector 可以改成bitset之类 +bool traverse(BlobTree tree, std::vector possiblePrimtivies, const std::vector& primitiveInout) +{ + assert(possiblePrimtivies.size() == tree.primtiveNodeIdx.size()); + for (int nodeIdx : tree.primtiveNodeIdx) { + propagate(tree, nodeIdx, primitiveInout[]); + if (tree.structure.back().inOut != 0) { return tree.structure.back().inOut == 1; } + } + std::cerr << "should not be here" << std::endl; + return false; +} }; // namespace algoim::organizer